[关闭]
@hainingwyx 2018-09-02T08:22:37.000000Z 字数 2264 阅读 968

python子进程subprocess

Python


subprocess包主要功能是执行外部的命令和程序。比如说,我需要使用wget下载文件。我在Python中调用wget程序。从这个意义上来说,subprocess的功能与shell类似。

subprocess包中定义有数个创建子进程的函数,这些函数分别以不同的方式创建子进程,所以我们可以根据需要来从中选取一个使用。另外subprocess还提供了一些管理标准流(standard stream)和管道(pipe)的工具,从而在进程间使用文本通信。

常用封装函数

subprocess.call():父进程等待子进程完成,返回退出信息
subprocess.check_call():父进程等待子进程完成,返回0,检查退出信息,如果returncode不为0,则举出错误subprocess.CalledProcessError,该对象包含有returncode属性,可用try...except...来检查

subprocess.check_output():父进程等待子进程完成,返回子进程向标准输出的输出结果。检查退出信息,如果returncode不为0,则举出错误subprocess.CalledProcessError,该对象包含有returncode属性和output属性,output属性为标准输出的输出结果,可用try...except...来检查。

举例说明:

  1. import subprocess
  2. out = subprocess.call("ls -l", shell=True)
  3. out = subprocess.call("cd ..", shell=True)

Popen

上面的三个函数都是基于Popen()的封装(wrapper)。这些封装的目的在于让我们容易使用子进程。当我们想要更个性化我们的需求的时候,就要转向Popen类,该类生成的对象用来代表子进程。

属性:
p.pid:子进程的PID
p.returncode:子进程的返回状态,即None —— 子进程尚未结束;==0 ——子进程正常退出;> 0—— 子进程异常退出,returncode对应于出错码;< 0—— 子进程被信号杀掉了。
p.stdin, p.stdout, p.stderr:子进程对应的一些初始文件,如果调用Popen()的时候对应的参数是subprocess.PIPE,则这里对应的属性是一个包裹了这个管道的 file 对象,

方法:
p.poll():检查子进程 p 是否已经终止,返回 p.returncode 属性
p.wait()

Popen对象创建后,主程序不会自动等待子进程完成。我们必须调用对象的wait()方法,父进程才会等待 (也就是阻塞block):

  1. import subprocess
  2. child = subprocess.Popen(["ping","-c","5","www.google.com"])
  3. print("parent process")

对比等待的情况:

  1. import subprocess
  2. child = subprocess.Popen(["ping","-c","5","www.google.com"])
  3. child.wait()
  4. print("parent process")

此外,还可以在父进程中对子进程进行其它操作:

  1. child.poll() # 检查子进程状态
  2. child.kill() # 终止子进程
  3. child.send_signal() # 向子进程发送信号
  4. child.terminate() # 终止子进程

文本流控制

子进程的标准输入,标准输出和标准错误也可以通过如下属性表示:
child.stdin
child.stdoutchild.stderr
可在Popen()建立子进程时改变标准输入、标准输出和标准错误,并可以利用subprocess.PIPE将多个子进程的输入和输出连接在一起,构成管道(pipe):

  1. import subprocess
  2. child1 = subprocess.Popen(["ls","-l"], stdout=subprocess.PIPE)
  3. child2 = subprocess.Popen(["wc"], stdin=child1.stdout,stdout=subprocess.PIPE)
  4. out = child2.communicate()
  5. print(out)

subprocess.PIPE实际上为文本流提供一个缓存区。child1的stdout将文本输出到缓存区,随后child2的stdin从该PIPE中将文本读取走。child2的输出文本也被存放在PIPE中,直到communicate()方法从PIPE中读取出PIPE中的文本。

要注意的是,communicate()是Popen对象的一个方法,该方法会阻塞父进程,直到子进程完成。

还可利用communicate()方法来使用PIPE给子进程输入:

  1. import subprocess
  2. child = subprocess.Popen(["cat"], stdin=subprocess.PIPE)
  3. child.communicate("test")

我们启动子进程之后,cat会等待输入,直到我们用communicate()输入"test"。

参考文献

http://www.cnblogs.com/vamei/archive/2012/09/23/2698014.html
https://www.cnblogs.com/Security-Darren/p/4733368.html

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注