subprocess-call, check_call, check_output, Popen

在Python中,我们通过使用标准库中的subprocess模块来fork一个子进程,并运行一个外部的程序(类似于在linux中fork一个子进程,然后在子进程中exec另外一个程序)。

这一模块中提供了多种方法:

call

1
subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False)
  1. 参数args描述了子进程中需要执行的命令;
  2. 父进程会等待子进程的结束,并获得call函数的返回值
1
2
3
4
5
6
7
import subprocess

cmd = ['ls', '-l];
ret = subprocess.call(cmd)

cmd = ['exit 1'];
ret = subprocess.call(cmd, shell=True);
  1. 如果子进程不需要进行交互,就可以使用该函数来创建

check_call

1
subprocess.check_call(args, *, stdin=None, stdout=None, stderr=None, shell=False)
  1. check_call()与call()唯一的区别在于返回值。如果args执行之后的返回值为0,那么check_all返回0;如果返回值不为0,那么将raise出来一个CalledProcessError

check_output

1
subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, universal_newlines=False)
  1. 子进程执行args中的命令,并将其输出形成字符串返回
  2. 如果返回值非零,那么将raise一个CalledProcessError。这一对象实例中有returncode属性以及output属性(args命令的output)

Popen

1
subprocess.Popen(args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=False, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0)
  1. Popen对象创建后,主程序不会自动等待子进程完成。我们必须调用对象的wait()方法,父进程才会等待 (也就是阻塞block)

  2. Popen中封装的其他函数 :

    1. Popen.poll():检查子进程的状态,查看子进程是否结束
    2. Popen.wait():等待子进程的结束
    3. Popen.communicate(input=None):与子进程进行交互。向stdin发送数据,或从stdout和stderr中读取数据。可选参数input指定发送到子进程的参数。Communicate()返回一个元组:(stdoutdata, stderrdata)。注意:如果希望通过进程的stdin向其发送数据,在创建Popen对象的时候,参数stdin必须被设置为PIPE。同样,如果希望从stdout和stderr获取数据,必须将stdout和stderr设置为PIPE。
    4. Popen.send_signal(signal):向子进程发送信号
    5. Popen.terminate():停止(stop)子进程。在windows平台下,该方法将调用Windows API TerminateProcess()来结束子进程
    6. Popen.kill():杀死子进程
    7. Popen.stdin:如果在创建Popen对象时,参数stdin被设置为PIPE,Popen.stdin将返回一个文件对象用于向子进程发送指令;否则返回None
    8. Popen.stdout:如果在创建Popen对象时,参数stdout被设置为PIPE,Popen.stdout将返回一个文件对象用于向子进程发送指令;否则返回None
    9. Popen.stderr:如果在创建Popen对象时,参数stderr被设置为PIPE,Popen.stderr将返回一个文件对象用于向子进程发送指令;否则返回None
    10. Popen.pid:获取子进程的进程ID
    11. Popen.returncode:获取进程的返回值。如果进程还没有结束,返回None

需要注意的是,在使用Popen.wait()方法等待子程序完成时,如果stdout或者stderr设置了PIPE,那么当子进程的输出超过操作系统的pipe size时,会导致死锁的情况。所以官方建议使用Popen.communicate()方法,因为子进程的输出是直接写入系统内存空间,一般不会超出内存上限。

参考资料

  1. subprocess模块学习-call, checkall, check_output, Popen
  2. Popen communicate() 和wait()使用上的区别
感谢你对我的支持,让我继续努力分享有用的技术和知识点