一、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