subprocess模块提供进程间操作
call方法创建一个子进程
retcode=subprocess.call(["ls","-l","-a"]) 结果: -rw------- 1 root root 1570 Feb 3 2015 anaconda-ks.cfg drwxr-xr-x 2 root root 4096 Feb 3 2015 Desktop -rw-r--r-- 1 root root 59038 Feb 3 2015 install.log -rw-r--r-- 1 root root 5266 Feb 3 2015 install.log.syslog -rw-r--r-- 1 root root 908984 May 18 12:29 nginx-1.9.15.tar.gz -rw-r--r-- 1 root root 2053336 May 18 18:12 pcre-8.38.tar.gz -rw-r--r-- 1 root root 18207283 May 18 18:13 php-7.0.6.tar.gz -rw-r--r-- 1 root root 148960 May 18 09:42 zabbix-2.2.1-1.el5.x86_64.rpm -rw-r--r-- 1 root root 248051 May 18 09:41 zabbix-agent-2.2.1-1.el5.x86_64.rpm -rw-r--r-- 1 root root 11296 May 18 09:33 zabbix-release-2.4-1.el6.noarch.rpm
在Linux下,shell=False时, Popen调用os.execvp()执行args指定的程序;shell=True时,如果args是字符串,Popen直接调用系统的Shell来执行args指定的程序,如果args是一个序列,则args的第一项是定义程序命令字符串,其它项是调用系统Shell时的附加参数。
>>> retcode=subprocess.call("ls -l",shell=True) total 21244 -rw------- 1 root root 1570 Feb 3 2015 anaconda-ks.cfg drwxr-xr-x 2 root root 4096 Feb 3 2015 Desktop -rw-r--r-- 1 root root 59038 Feb 3 2015 install.log -rw-r--r-- 1 root root 5266 Feb 3 2015 install.log.syslog -rw-r--r-- 1 root root 908984 May 18 12:29 nginx-1.9.15.tar.gz -rw-r--r-- 1 root root 2053336 May 18 18:12 pcre-8.38.tar.gz -rw-r--r-- 1 root root 18207283 May 18 18:13 php-7.0.6.tar.gz -rw-r--r-- 1 root root 148960 May 18 09:42 zabbix-2.2.1-1.el5.x86_64.rpm -rw-r--r-- 1 root root 248051 May 18 09:41 zabbix-agent-2.2.1-1.el5.x86_64.rpm -rw-r--r-- 1 root root 11296 May 18 09:33 zabbix-release-2.4-1.el6.noarch.rpm
实际上,上面的几个函数都是基于Popen()的封装(wrapper)。这些封装的目的在于让我们容易使用子进程。当我们想要更个性化我们的需求的时候,就要转向Popen类,该类生成的对象用来代表子进程。
与上面的封装不同,Popen对象创建后,主程序不会自动等待子进程完成。我们必须调用对象的wait()方法,父进程才会等待 (也就是阻塞block),举例:
import subprocess
child = subprocess.Popen(['ping','-n','4','blog.linuxeye.com'])
# child.wait()
print ('parent process')
结果:
从运行结果中看到,父进程在开启子进程之后并没有等待child的完成,而是直接运行print。
parent process
import subprocess child = subprocess.Popen(['ping','-n','4','blog.linuxeye.com']) child.wait() print ('parent process')
结果:(先等待子进程完成) 正在 Ping blog.linuxeye.com [121.40.145.83] 具有 32 字节的数据: 来自 121.40.145.83 的回复: 字节=32 时间=29ms TTL=52 来自 121.40.145.83 的回复: 字节=32 时间=33ms TTL=52 来自 121.40.145.83 的回复: 字节=32 时间=30ms TTL=52 来自 121.40.145.83 的回复: 字节=32 时间=32ms TTL=52 121.40.145.83 的 Ping 统计信息: 数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失), 往返行程的估计时间(以毫秒为单位): 最短 = 29ms,最长 = 33ms,平均 = 31ms parent process
在父进程等待的时候,还可以对子进程做其他的操作
child.poll() # 检查子进程状态 child.kill() # 终止子进程 child.send_signal() # 向子进程发送信号 child.terminate() # 终止子进程
子进程的标准输入、标准输出和标准错误如下属性分别表示:
child.stdin
child.stdout
child.stderr
可以在Popen()建立子进程的时候改变标准输入、标准输出和标准错误,并可以利用subprocess.PIPE将多个子进程的输入和输出连接在一起,构成管道(pipe),如下2个例子:
把输出放入到stdout中,然后从stdout中读出来
>>> child1 = subprocess.Popen(["ls","-l"], stdout=subprocess.PIPE) >>> print child1.stdout.read() total 21244 -rw------- 1 root root 1570 Feb 3 2015 anaconda-ks.cfg drwxr-xr-x 2 root root 4096 Feb 3 2015 Desktop -rw-r--r-- 1 root root 59038 Feb 3 2015 install.log -rw-r--r-- 1 root root 5266 Feb 3 2015 install.log.syslog -rw-r--r-- 1 root root 908984 May 18 12:29 nginx-1.9.15.tar.gz -rw-r--r-- 1 root root 2053336 May 18 18:12 pcre-8.38.tar.gz -rw-r--r-- 1 root root 18207283 May 18 18:13 php-7.0.6.tar.gz -rw-r--r-- 1 root root 148960 May 18 09:42 zabbix-2.2.1-1.el5.x86_64.rpm -rw-r--r-- 1 root root 248051 May 18 09:41 zabbix-agent-2.2.1-1.el5.x86_64.rpm -rw-r--r-- 1 root root 11296 May 18 09:33 zabbix-release-2.4-1.el6.noarch.rpm
>>> import subprocess >>> child1 = subprocess.Popen(["cat","/etc/passwd"], stdout=subprocess.PIPE) >>> child2 = subprocess.Popen(["grep","0:0"],stdin=child1.stdout, stdout=subprocess.PIPE) >>> out = child2.communicate() >>> print out ('root:x:0:0:root:/root:/bin/bash ', None)
>>> import subprocess
>>> child1 = subprocess.Popen(["cat","/etc/passwd"], stdout=subprocess.PIPE)
>>> child2 = subprocess.Popen(["grep","0:0"],stdin=child1.stdout, stdout=subprocess.PIPE)
>>> print child2.stdout.read
<built-in method read of file object at 0x2b5838884be8>
>>> print child2.stdout.read()
root:x:0:0:root:/root:/bin/bash