一、subprocess 模块简介
subprocess最早是在2.4版本中引入的。
subprocess模块用来生成子进程,并可以通过管道连接它们的输入/输出/错误,以及获得它们的返回值。它用来代替多个旧模块和函数:os.systemos.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)1WARNING: 使用 shell=True 是一种安全保护机制。NOTE: 在使用这个函数时,不要使用 stdout=PIPE 或 stderr=PIPE 参数, 不然会导致子进程输出的死锁。 如果要使用管道,可以在 communicate()方法中使用Popen 示例代码:import subprocessrc = subprocess.call(["ls","-l"])
通过一个shell来解释一整个字符串:
import subprocessout = 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 subprocessret1 = subprocess.Popen(["mkdir","t1"])ret2 = subprocess.Popen("mkdir t2", shell=True)
终端输入的命令分为两种:
·输入即可得到输出,如:ifconfig
·输入进行某环境,依赖再输入,如:python
import subprocessobj = subprocess.Popen("mkdir t3", shell=True, cwd='/home/dev',)
import subprocessobj = 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 subprocessobj = 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 subprocessobj = 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 subprocesschild = subprocess.Popen(["cat"], stdin=subprocess.PIPE)child.communicate("vamei")
启动子进程之后,cat会等待输入,直到我们用communicate()输入"vamei"。
详文参见: