一、subprocess 模块简介

subprocess最早是在2.4版本中引入的。
subprocess模块用来生成子进程,并可以通过管道连接它们的输入/输出/错误,以及获得它们的返回值。
它用来代替多个旧模块和函数:
os.system
os.spawn*
os.popen*
popen2.*
commands.*


1.1. 使用 subprocess模块

启动子进程的推荐方式是使用下面的便利功能。
当这些还不能满足需求时,就需要使用底层的Popen接口。

1. subprocess.call

语法:
     subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False)
语义:
     运行由args指定的命令,直到命令结束后,返回 返回码的属性值。

示例代码:
>>> subprocess.call(["ls", "-l"])
0
>>> subprocess.call("exit 1", shell=True)
1

WARNING: 使用 shell=True 是一种安全保护机制。
NOTE: 在使用这个函数时,不要使用 stdout=PIPE 或 stderr=PIPE 参数,
      不然会导致子进程输出的死锁。
      如果要使用管道,可以在 communicate()方法中使用Popen
      
示例代码:
import subprocess
rc = subprocess.call(["ls","-l"])


通过一个shell来解释一整个字符串:

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

使用了shell=True这个参数。
这个时候,我们使用一整个字符串,而不是一个表来运行子进程。
Python将先运行一个shell,再用这个shell来解释这整个字符串。

shell命令中有一些是shell的内建命令,这些命令必须通过shell运行,$cd。
shell=True允许我们运行这样一些命令。


2. subprocess.check_call

语法: 
     subprocess.check_call(args, *, stdin=None, stdout=None, stderr=None, shell=False)
语义:
     运行由args指定的命令,直到命令执行完成。
     如果返回码为零,则返回。否则,抛出 CalledProcessError异常。
     CalledProcessError对象包含有返回码的属性值。

上面显示的参数仅仅是最常见的,下面是用户更常用的参数。
示例代码如下:

>>>
>>> subprocess.check_call(["ls", "-l"])
0
>>> subprocess.check_call("exit 1", shell=True)
Traceback (most recent call last):
   ...
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1

这个函数在python 2.5版本中引入。
WARNING: 使用 shell=True 是一种安全机制。
NOTE: 不要在这个函数中使用 stdout=PIPE 或 stderr=PIPE, 否则会造成子进程死锁。
      如果需要使用管道,可以在 communicate()方法中使用Popen.


3. subprocess.check_output

语法: 
      subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, universal_newlines=False)
语义:
     运行args定义的命令,并返回一个字符串表示的输出值。
     如果返回码为非零,则抛出 CalledProcessError异常。
示例代码:
>>>
>>> subprocess.check_output(["echo", "Hello World!"])
'Hello World!\n'
>>> subprocess.check_output("exit 1", shell=True)
Traceback (most recent call last):
   ...
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1
如果要捕捉结果中的标准错误,使用 stderr=subprocess.STDOUT参数:
>>>
>>> subprocess.check_output(
...     "ls non_existent_file; exit 0",
...     stderr=subprocess.STDOUT,
...     shell=True)
'ls: non_existent_file: No such file or directory\n'

这个函数在python 2.7版本中引入。
WARNING: 使用 shell=True 是一种安全机制。
NOTE: 不要在这个函数中使用 stdout=PIPE 或 stderr=PIPE, 否则会造成子进程死锁。
      如果需要使用管道,可以在 communicate()方法中使用Popen.


4.subprocess.Popen(...)

用于执行复杂的系统命令

参数:

·args:shell命令,可以是字符串或者序列类型(如:list,元组)

·bufsize:指定缓冲。0 无缓冲,1 行缓冲,其他 缓冲区大小,负值 系统缓冲

·stdin, stdout, stderr:分别表示程序的标准输入、输出、错误句柄

·preexec_fn:只在Unix平台下有效,用于指定一个可执行对象(callable object),它将在子进程运行之前被调用

·close_sfs:在windows平台下,如果close_fds被设置为True,则新创建的子进程将不会继承父进程的输入、输出、错误管道。所以不能将close_fds设置为True同时重定向子进程的标准输入、输出与错误(stdin, stdout, stderr)。

·shell:同上

·cwd:用于设置子进程的当前目录

·env:用于指定子进程的环境变量。如果env = None,子进程的环境变量将从父进程中继承。

·universal_newlines:不同系统的换行符不同,True -> 同意使用 \n

·startupinfo与createionflags只在windows下有效
将被传递给底层的CreateProcess()函数,用于设置子进程的一些属性,如:主窗口的外观,进程的优先级等等

import subprocess
ret1 = subprocess.Popen(["mkdir","t1"])
ret2 = subprocess.Popen("mkdir t2", shell=True)

终端输入的命令分为两种:

·输入即可得到输出,如:ifconfig

·输入进行某环境,依赖再输入,如:python

import subprocess

obj = subprocess.Popen("mkdir t3", shell=True, cwd='/home/dev',)
import subprocess

obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
obj.stdin.write("print(1)\n")
obj.stdin.write("print(2)")
obj.stdin.close()

cmd_out = obj.stdout.read()
obj.stdout.close()
cmd_error = obj.stderr.read()
obj.stderr.close()print(cmd_out)print(cmd_error)
import subprocess

obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
obj.stdin.write("print(1)\n")
obj.stdin.write("print(2)")

out_error_list = obj.communicate()print(out_error_list)
import subprocess

obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
out_error_list = obj.communicate('print("hello")')
print(out_error_list)

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

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

import subprocess
child = subprocess.Popen(["cat"], stdin=subprocess.PIPE)
child.communicate("vamei")

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



详文参见:http://www.cnblogs.com/vamei/archive/2012/09/23/2698014.html

http://blog.chinaunix.net/uid-26000296-id-4461522.html