What difference between subprocess.call() and subprocess.Popen() makes PIPE less secure for the former?

别来无恙 提交于 2019-11-30 04:56:28
jfs

call() is just Popen().wait() (± error handling).

You should not use stdout=PIPE with call() because it does not read from the pipe and therefore the child process will hang as soon as it fills the corresponding OS pipe buffer. Here's a picture that shows how data flows in command1 | command2 shell pipeline:

It does not matter what your Python version is -- the pipe buffer (look at the picture) is outside of your Python process. Python 3 does not use C stdio but it affects only the internal buffering. When the internal buffer is flushed the data goes into the pipe. If command2 (your parent Python program) does not read from the pipe then command1 (the child process e.g., started by call()) will hang as soon as the pipe buffer is full (pipe_size = fcntl(p.stdout, F_GETPIPE_SZ) ~65K on my Linux box (max value is /proc/sys/fs/pipe-max-size ~1M)).

You may use stdout=PIPE if you read from the pipe later e.g., using Popen.communicate() method. You could also read from process.stdout (the file object that represents the pipe) directly.

Both call and Popen provide means of accessing the output of your command:

  • With Popen you can use communicate or provide a file descriptor or file object to the stdout=... parameter.
  • With call your only option is to pass a file descriptor or a file object to the stdout=... parameter (you can not use communicate with this one).

Now, the reason why stdout=PIPE is insecure when used with call is because call doesn't return until the subprocess has finished, this means all the output would have to reside in memory until that moment, and if the amount of output is too much then that would fill the OS pipes' buffer.

The references where you can validate the above information are the following:

  1. According to this the parameters for both call and Popen are the same:

The arguments shown above are merely the most common ones, described below in Frequently Used Arguments (hence the slightly odd notation in the abbreviated signature). The full function signature is the same as that of the Popen constructor - this functions passes all supplied arguments directly through to that interface.

  1. According to this the possible values for the stdout parameter are:

Valid values are PIPE, an existing file descriptor (a positive integer), an existing file object, and None. PIPE indicates that a new pipe to the child should be created

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!