Python 子进程管理–subprocess

  • A+
所属分类:Python库介绍
摘要这一篇文章介绍 Python 的一个标准库,subprocess,使用他可以对 python 的子进程进行管理,也可以在 python 脚本中运行一些外部的程序。

简介

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

通过使用 subprocess 包,我们可以运行外部程序。这极大的拓展了Python的功能。如果你已经了解了操作系统的某些应用,你可以从 Python 中直接调用该应用 (而不是完全依赖 Python ),并将应用的结果输出给 Python,并让 Python 继续处理。(摘自,Python标准库06 子进程 (subprocess包)

参考资料

 

subprocess 即常见的封装函数

当我们允许 python 程序的时候,我们是创建了一个进程。一个进程可以 fork 一个子进程,这个子进程可以运行另外一个程序。在 python 中,我们可以使用标准库 subprocess 来fork 一个子进程,并运行外部程序。

在使用 subprocess 创建子进程的时候,有以下几个点需要注意:

  1. 当创建子进程之后,父进程是否暂停,等待子进程运行;
  2. 子进程返回是什么;
  3. 当 returncode 不是 0 的时候,父进程应该如何处理;

 

subprocess.call

subprocess.call 是父进程等待子进程完成,同时返回 return code。下面看一个简单的例子。

  1. import subprocess
  2. rc = subprocess.call(["dir"], shell=True)

我们使用了 shell=True 这个参数。这个时候,Python将先运行一个shell,再用这个shell来解释这整个字符串。我们在 windows 下运行一些 exe 的时候,也需要使用 shell=True 的方式来进行运行。

 

subprocess.Popen

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

与上面的封装不同,Popen 对象创建后,主程序不会自动等待子进程完成。我们必须调用对象的wait() 方法,父进程才会等待。可以看下面的例子,

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

父进程在开启子进程之后,没有等待,而是先进行 print 之后,才开始有子进程的信息。

Python 子进程管理--subprocess

我们需要使用 child.wait() 来是的父进程等待子进程的完成。

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

可以看到此时父进程是等子进程运行完毕之后才开始运行的。

Python 子进程管理--subprocess

 

子进程的输入输入异常控制

在使用 Popen 的时候,我们可以分别控制子进程的标准输入和输出,和子进程的异常。这些分别是:

  • child.stdin,标准输入
  • child.stdout,标准输出
  • child.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.decode('gb2312'))

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

其中,communicate() 是Popen对象的一个方法,该方法会阻塞父进程,直到子进程完成。同时要注意,在 windows 下输出的编码,可能需要使用 decode('gb2312') 来进行解码才可以正常显示。

我们可以借助其来运行一些 windows 下的 exe 的程序,例如下面运行 editcap.exe 来进行流量的分割,可以在其中指定参数,具体的可以参考下面的写法。

  1. prog = subprocess.Popen(["editcap.exe",
  2.                 "-F", "libpcap",
  3.                 "-T", "ether",
  4.                 '1.pcapng',
  5.                 '1.pcap'],
  6.             stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
  7. _, _ = prog.communicate()

 

  • 微信公众号
  • 关注微信公众号
  • weinxin
  • QQ群
  • 我们的QQ群号
  • weinxin
王 茂南

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: