在Python中,我们通过使用标准库中的subprocess模块来fork一个子进程,并运行一个外部的程序(类似于在linux中fork一个子进程,然后在子进程中exec另外一个程序)。
这一模块中提供了多种方法:
call
1 | subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False) |
- 参数args描述了子进程中需要执行的命令;
- 父进程会等待子进程的结束,并获得call函数的返回值
1 | import subprocess |
- 如果子进程不需要进行交互,就可以使用该函数来创建
check_call
1 | subprocess.check_call(args, *, stdin=None, stdout=None, stderr=None, shell=False) |
- 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) |
- 子进程执行args中的命令,并将其输出形成字符串返回
- 如果返回值非零,那么将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) |
Popen对象创建后,主程序不会自动等待子进程完成。我们必须调用对象的wait()方法,父进程才会等待 (也就是阻塞block)
Popen中封装的其他函数 :
- Popen.poll():检查子进程的状态,查看子进程是否结束
- Popen.wait():等待子进程的结束
- Popen.communicate(input=None):与子进程进行交互。向stdin发送数据,或从stdout和stderr中读取数据。可选参数input指定发送到子进程的参数。Communicate()返回一个元组:(stdoutdata, stderrdata)。注意:如果希望通过进程的stdin向其发送数据,在创建Popen对象的时候,参数stdin必须被设置为PIPE。同样,如果希望从stdout和stderr获取数据,必须将stdout和stderr设置为PIPE。
- Popen.send_signal(signal):向子进程发送信号
- Popen.terminate():停止(stop)子进程。在windows平台下,该方法将调用Windows API TerminateProcess()来结束子进程
- Popen.kill():杀死子进程
- Popen.stdin:如果在创建Popen对象时,参数stdin被设置为PIPE,Popen.stdin将返回一个文件对象用于向子进程发送指令;否则返回None
- Popen.stdout:如果在创建Popen对象时,参数stdout被设置为PIPE,Popen.stdout将返回一个文件对象用于向子进程发送指令;否则返回None
- Popen.stderr:如果在创建Popen对象时,参数stderr被设置为PIPE,Popen.stderr将返回一个文件对象用于向子进程发送指令;否则返回None
- Popen.pid:获取子进程的进程ID
- Popen.returncode:获取进程的返回值。如果进程还没有结束,返回None
需要注意的是,在使用Popen.wait()
方法等待子程序完成时,如果stdout
或者stderr
设置了PIPE
,那么当子进程的输出超过操作系统的pipe size时,会导致死锁的情况。所以官方建议使用Popen.communicate()
方法,因为子进程的输出是直接写入系统内存空间,一般不会超出内存上限。