一、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)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"。

详文参见: