Skip to main content

17.5. subprocess —子进程管理

源代码: Lib/subprocess.py


subprocess 模块允许您生成新进程,连接到其输入/输出/错误管道,并获取其返回码。此模块旨在替换多个旧模块和函数:

os.system
os.spawn*

有关如何使用 subprocess 模块来替换这些模块和功能的信息,请参见以下部分。

参见

PEP 324 - PEP提出子过程模块

17.5.1. 使用 subprocess 模块

调用子进程的推荐方法是对所有可以处理的用例使用 run() 函数。对于更高级的用例,可以直接使用基础 Popen 接口。

run() 函数在Python 3.5中添加;如果您需要保留与旧版本的兼容性,请参阅 较旧的高级API 部分。

subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, shell=False, timeout=None, check=False, encoding=None, errors=None)

运行 args 描述的命令。等待命令完成,然后返回一个 CompletedProcess 实例。

上面显示的参数仅仅是最常见的参数,下面在 常用参数 中描述(因此在缩写签名中使用仅关键字符号)。完整的函数签名在很大程度上与 Popen 构造函数相同 - 除了 timeoutinputcheck 之外,这个函数的所有参数都被传递到该接口。

默认情况下,这不捕获stdout或stderr。为此,为 stdout 和/或 stderr 参数传递 PIPE

timeout 参数传递给 Popen.communicate()。如果超时过期,子进程将被终止并等待。子进程终止后,TimeoutExpired 异常将重新启动。

input 参数传递给 Popen.communicate(),因此传递给子进程的stdin。如果使用,它必须是字节序列,或者如果指定了 encodingerrorsuniversal_newlines 为真,则为字符串。使用时,将使用 stdin=PIPE 自动创建内部 Popen 对象,并且也可能不使用 stdin 参数。

如果 check 为真,并且进程以非零退出代码退出,则会引发 CalledProcessError 异常。该异常的属性保存参数,退出代码以及stdout和stderr(如果它们被捕获)。

如果指定了 encodingerrors,或 universal_newlines 为真,则使用指定的 encodingerrorsio.TextIOWrapper 默认值在文本模式下打开stdin,stdout和stderr的文件对象。否则,将以二进制模式打开文件对象。

例子:

>>> subprocess.run(["ls", "-l"])  # doesn't capture output
CompletedProcess(args=['ls', '-l'], returncode=0)

>>> subprocess.run("exit 1", shell=True, check=True)
Traceback (most recent call last):
  ...
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1

>>> subprocess.run(["ls", "-l", "/dev/null"], stdout=subprocess.PIPE)
CompletedProcess(args=['ls', '-l', '/dev/null'], returncode=0,
stdout=b'crw-rw-rw- 1 root root 1, 3 Jan 23 16:23 /dev/null\n')

3.5 新版功能.

在 3.6 版更改: 添加了 encodingerrors 参数

class subprocess.CompletedProcess

run() 的返回值,表示已完成的进程。

args

用于启动进程的参数。这可以是列表或字符串。

returncode

子进程的退出状态。通常,退出状态为0表示它已成功运行。

负值 -N 表示孩子被信号 N (仅POSIX)终止。

stdout

从子进程捕获stdout。字节序列,或者如果 run() 被编码或错误调用的字符串。 None 如果没有捕获stdout。

如果使用 stderr=subprocess.STDOUT 运行进程,stdout和stderr将在此属性中组合,stderr 将是 None

stderr

从子进程捕获stderr。字节序列,或者如果 run() 被编码或错误调用的字符串。 None 如果stderr没有捕获。

check_returncode()

如果 returncode 非零,提出 CalledProcessError

3.5 新版功能.

subprocess.DEVNULL

可用作 Popenstdinstdoutstderr 参数的特殊值,表示将使用特殊文件 os.devnull

3.3 新版功能.

subprocess.PIPE

可用作 Popenstdinstdoutstderr 参数的特殊值,指示应打开标准流的管道。最有用的是 Popen.communicate()

subprocess.STDOUT

可用作 Popenstderr 参数的特殊值,指示标准错误应与标准输出进入相同的句柄。

exception subprocess.SubprocessError

此模块的所有其他异常的基类。

3.3 新版功能.

exception subprocess.TimeoutExpired

SubprocessError 的子类,当超时在等待子进程时超时时引发。

cmd

用于生成子进程的命令。

timeout

超时(以秒为单位)。

output

子进程的输出(如果它由 run()check_output() 捕获)。否则,None

stdout

输出的别名,用于与 stderr 对称。

stderr

如果 run() 捕获了子进程的Stderr输出。否则,None

3.3 新版功能.

在 3.5 版更改: stdoutstderr 属性

exception subprocess.CalledProcessError

SubprocessError 的子类,当由 check_call()check_output() 运行的进程返回非零退出状态时引发。

returncode

子进程的退出状态。如果过程由于信号而退出,则这将是负信号数。

cmd

用于生成子进程的命令。

output

子进程的输出(如果它由 run()check_output() 捕获)。否则,None

stdout

输出的别名,用于与 stderr 对称。

stderr

如果 run() 捕获了子进程的Stderr输出。否则,None

在 3.5 版更改: stdoutstderr 属性

17.5.1.1. 常用参数

为了支持各种各样的用例,Popen 构造函数(和方便函数)接受大量的可选参数。对于大多数典型的用例,许多这些参数可以安全地保留其默认值。最常需要的参数是:

所有调用都需要 args,它应该是一个字符串或一系列程序参数。提供参数序列通常是优选的,因为它允许模块处理任何所需的转义和引用参数(例如,以允许文件名中的空格)。如果传递单个字符串,shell 必须是 True (见下文),否则字符串必须简单地命名要执行的程序,而不指定任何参数。

stdinstdoutstderr 分别指定执行程序的标准输入,标准输出和标准错误文件句柄。有效值为 PIPEDEVNULL,现有文件描述符(正整数),现有文件对象和 NonePIPE 表示应该创建一个新的管道给孩子。 DEVNULL 指示将使用特殊文件 os.devnull。使用 None 的默认设置,不会发生重定向;子进程的文件句柄将从父进程继承。另外,stderr 可以是 STDOUT,其指示来自子进程的stderr数据应被捕获到与用于 stdout 的相同的文件句柄中。

如果指定了 encodingerrors,或 universal_newlines 为真,则将在文本模式下使用调用中指定的 encodingerrorsio.TextIOWrapper 的默认值打开文件对象 stdinstdoutstderr

对于 stdin,输入中的行结束字符 '\n' 将转换为默认行分隔符 os.linesep。对于 stdoutstderr,输出中的所有行结尾将转换为 '\n'。有关更多信息,请参阅 io.TextIOWrapper 类的文档,当其构造函数的 newline 参数为 None 时。

如果不使用文本模式,则 stdinstdoutstderr 将作为二进制流打开。不执行编码或行结束转换。

3.6 新版功能: 添加了 encodingerrors 参数。

注解

文件对象 Popen.stdinPopen.stdoutPopen.stderr 的换行符属性不通过 Popen.communicate() 方法更新。

如果 shellTrue,指定的命令将通过shell执行。如果您使用Python主要用于其提供的大多数系统shell的增强控制流,并且仍然希望方便地访问其他shell功能(如shell管道,文件名通配符,环境变量扩展和将 ~ 扩展到用户的家庭),这将非常有用目录。但是,请注意,Python本身提供了许多类shell特性(特别是 globfnmatchos.walk()os.path.expandvars()os.path.expanduser()shutil)的实现。

在 3.3 版更改: universal_newlinesTrue 时,该类使用编码 locale.getpreferredencoding(False) 而不是 locale.getpreferredencoding()。有关此更改的更多信息,请参阅 io.TextIOWrapper 类。

注解

在使用 shell=True 之前阅读 Security Considerations 部分。

这些选项以及所有其他选项在 Popen 构造函数文档中有更详细的描述。

17.5.1.2. Popen构造函数

此模块中的基础过程创建和管理由 Popen 类处理。它提供了很多灵活性,以便开发人员能够处理方便功能未涵盖的较不常见的情况。

class subprocess.Popen(args, bufsize=-1, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=True, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0, restore_signals=True, start_new_session=False, pass_fds=(), *, encoding=None, errors=None)

在新进程中执行子程序。在POSIX上,类使用类似 os.execvp() 的行为来执行子程序。在Windows上,类使用Windows CreateProcess() 功能。 Popen 的参数如下。

args 应该是一个程序参数序列或者一个单个字符串。默认情况下,如果 args 是序列,则要执行的程序是 args 中的第一个项目。如果 args 是字符串,解释是平台相关的,如下所述。有关与默认行为的其他差异,请参阅 shellexecutable 参数。除非另有说明,建议将 args 作为序列传递。

在POSIX上,如果 args 是字符串,则该字符串被解释为要执行的程序的名称或路径。但是,这只能在不将参数传递给程序时才能实现。

注解

shlex.split() 在确定 args 的正确标记化时非常有用,尤其是在复杂情况下:

>>> import shlex, subprocess
>>> command_line = input()
/bin/vikings -input eggs.txt -output "spam spam.txt" -cmd "echo '$MONEY'"
>>> args = shlex.split(command_line)
>>> print(args)
['/bin/vikings', '-input', 'eggs.txt', '-output', 'spam spam.txt', '-cmd', "echo '$MONEY'"]
>>> p = subprocess.Popen(args) # Success!

特别要注意的是,由shell中的空格分隔的选项(如 -input)和参数(如 eggs.txt)位于单独的列表元素中,而在shell中使用时需要引号或反斜杠转义的参数(例如包含空格的文件名或上面显示的 echo 命令)是单列表元素。

在Windows上,如果 args 是序列,它将以 在Windows上将参数序列转换为字符串 中描述的方式转换为字符串。这是因为底层的 CreateProcess() 在字符串上操作。

shell 参数(默认为 False)指定是否使用shell作为程序执行。如果 shellTrue,则建议将 args 作为字符串而不是序列传递。

在带有 shell=True 的POSIX上,shell默认为 /bin/sh。如果 args 是字符串,则该字符串指定要通过shell执行的命令。这意味着该字符串的格式必须与在shell提示符下输入时的格式完全相同。这包括,例如,引用或反斜杠转义文件名中带有空格。如果 args 是序列,则第一个项指定命令字符串,任何其他项将被视为shell本身的附加参数。也就是说,Popen 相当于:

Popen(['/bin/sh', '-c', args[0], args[1], ...])

在具有 shell=True 的Windows上,COMSPEC 环境变量指定默认shell。只有当你需要在Windows上指定 shell=True 时,你希望执行的命令被内置到shell中(例如 dircopy)。您不需要 shell=True 来运行批处理文件或基于控制台的可执行文件。

注解

在使用 shell=True 之前阅读 Security Considerations 部分。

在创建stdin/stdout/stderr管道文件对象时,bufsize 将作为 open() 函数的相应参数提供:

  • 0 表示无缓冲(读写是一个系统调用,可以返回短)

  • 1 意味着行缓冲(仅在 universal_newlines=True 即在文本模式中可用时)

  • 任何其他正值意味着使用大约该大小的缓冲器

  • 负BUFSIZE(默认值)表示io.DEFAULT_BUFFER_SIZE系统默认将被使用。

在 3.3.1 版更改: bufsize 现在默认为-1,默认情况下启用缓冲,以匹配大多数代码所期望的行为。在Python 3.2.4和3.3.1之前的版本中,它不正确地默认为 0,它是未缓冲的,允许短读。这是无意的,并且不匹配Python 2的行为,因为大多数代码预期。

executable 参数指定要执行的替换程序。这是很少需要。当 shell=Falseexecutable 替换由 args 指定的执行程序时。然而,原来的 args 仍然传递给程序。大多数程序将由 args 指定的程序视为命令名称,这可能与实际执行的程序不同。在POSIX上,args 名称成为实用程序(如 ps)中可执行文件的显示名称。如果 shell=True,在POSIX上,executable 参数指定默认 /bin/sh 的替换shell。

stdinstdoutstderr 分别指定执行程序的标准输入,标准输出和标准错误文件句柄。有效值为 PIPEDEVNULL,现有文件描述符(正整数),现有 file objectNonePIPE 表示应该创建一个新的管道给孩子。 DEVNULL 表示将使用特殊文件 os.devnull。使用 None 的默认设置,不会发生重定向;子进程的文件句柄将从父进程继承。此外,stderr 可以是 STDOUT,这表示来自应用程序的stderr数据应该捕获到与stdout相同的文件句柄中。

如果 preexec_fn 被设置为可调用对象,则该对象将在子进程中在子进程执行之前被调用。 (仅POSIX)

警告

preexec_fn 参数在应用程序中存在线程时不安全使用。在调用exec之前,子进程可能死锁。如果你必须使用它,保持它琐碎!最小化调用的库的数量。

注解

如果你需要修改环境为孩子使用 env 参数,而不是在 preexec_fn 中。 start_new_session 参数可以取代以前常用的 preexec_fn 在子进程中调用os.setsid()。

如果 close_fds 为真,除了 012 之外的所有文件描述符在执行子进程之前都将关闭。 (仅POSIX)。默认值因平台而异:在POSIX上始终为true。在Windows上,当 stdin/stdout/stderrNone 时是真的,否则为假。在Windows上,如果 close_fds 为true,则子进程将不继承任何句柄。请注意,在Windows上,您不能将 close_fds 设置为true,也可以通过设置 stdinstdoutstderr 重定向标准句柄。

在 3.2 版更改: close_fds 的默认值从 False 更改为上述内容。

pass_fds 是文件描述符的可选序列,以在父级和子级之间保持打开。提供任何 pass_fdsclose_fdsTrue。 (仅POSIX)

3.2 新版功能: 添加了 pass_fds 参数。

如果 cwd 不是 None,则函数在执行子代之前将工作目录更改为 cwd。特别地,如果可执行路径是相对路径,则该函数查找相对于 cwdexecutable (或针对 args 中的第一项)。

如果 restore_signals 为true(默认值),Python已经设置为SIG_IGN的所有信号在exec进程之前的子进程中恢复为SIG_DFL。目前,这包括SIGPIPE,SIGXFZ和SIGXFSZ信号。 (仅POSIX)

在 3.2 版更改: 加入 restore_signals

如果 start_new_session 为真,setsid()系统调用将在子进程中执行子进程之前进行。 (仅POSIX)

在 3.2 版更改: 加入 start_new_session

如果 env 不是 None,它必须是定义新进程的环境变量的映射;这些被用来代替继承当前进程环境的默认行为。

注解

如果指定,env 必须提供程序执行所需的任何变量。在Windows上,为了运行 side-by-side assembly,指定的 env 必须 包括有效的 SystemRoot

如果指定 encodingerrors,则文本对象 stdinstdoutstderr 在具有指定编码和 errors 的文本模式中打开,如上面在 常用参数 中所述。如果 universal_newlinesTrue,它们将在默认编码的文本模式下打开。否则,它们将作为二进制流打开。

3.6 新版功能: encodingerrors

如果给出,startupinfo 将是一个 STARTUPINFO 对象,它被传递给底层的 CreateProcess 函数。 creationflags,如果给出,可以是 CREATE_NEW_CONSOLECREATE_NEW_PROCESS_GROUP。 (仅限Windows)

通过 with 语句支持Popen对象作为上下文管理器:在退出时,关闭标准文件描述符,并等待进程。

with Popen(["ifconfig"], stdout=PIPE) as proc:
    log.write(proc.stdout.read())

在 3.2 版更改: 添加了上下文管理器支持。

在 3.6 版更改: Popen析构函数现在发出一个 ResourceWarning 警告,如果子进程仍在运行。

17.5.1.3. 例外

子进程中引发的异常在新程序开始执行之前将在父进程中重新生成。此外,异常对象将有一个额外的属性称为 child_traceback,它是一个字符串,包含从孩子的角度的追溯信息。

最常见的例外是 OSError。例如,当尝试执行不存在的文件时,会发生这种情况。应用程序应准备 OSError 异常。

如果使用无效参数调用 Popen,将会引发 ValueError

如果被调用的进程返回非零返回码,check_call()check_output() 将引发 CalledProcessError

接受 timeout 参数的所有函数和方法(例如 call()Popen.communicate())将在进程退出之前超时超时时引发 TimeoutExpired

本模块中定义的异常都继承自 SubprocessError

3.3 新版功能: 添加了 SubprocessError 基类。

17.5.2. 安全注意事项

与一些其他popen函数不同,此实现不会隐式调用系统shell。这意味着所有字符,包括shell元字符,都可以安全地传递给子进程。如果shell被显式调用,通过 shell=True,应用程序有责任确保所有空格和元字符被适当引用以避免 壳注射 漏洞。

当使用 shell=True 时,shlex.quote() 函数可以用于正确地转换将要用于构建shell命令的字符串中的空格和shell元字符。

17.5.3. Popen对象

Popen 类的实例具有以下方法:

Popen.poll()

检查子进程是否已终止。设置和返回 returncode 属性。

Popen.wait(timeout=None)

等待子进程终止。设置和返回 returncode 属性。

如果进程在 timeout 秒后未终止,则引发 TimeoutExpired 异常。捕获此异常并重试等待是安全的。

注解

这将在使用 stdout=PIPEstderr=PIPE 时死锁,子进程为管道生成足够的输出,以阻止等待OS管道缓冲区接受更多数据。使用 Popen.communicate() 时,使用管道,以避免这一点。

注解

该功能使用忙循环(非阻塞调用和短暂休眠)实现。使用 asyncio 模块进行异步等待:请参阅 asyncio.create_subprocess_exec

在 3.3 版更改: 加入 timeout

3.4 版后已移除: 不要使用 endtime 参数。它在3.3中是无意暴露的,但是没有记录,因为它是私人内部使用。使用 timeout

Popen.communicate(input=None, timeout=None)

与进程交互:将数据发送到stdin。从stdout和stderr读取数据,直到达到文件结束。等待进程终止。可选的 input 参数应该是要发送到子进程的数据,或 None,如果没有数据应发送到子进程。如果在文本模式下打开流,input 必须是字符串。否则,它必须是字节。

communicate() 返回一个元组 (stdout_data, stderr_data)。如果以文本模式打开流,数据将是字符串;否则,字节。

注意,如果你想发送数据到进程的stdin,你需要用 stdin=PIPE 创建Popen对象。类似地,要在结果元组中获得除 None 以外的任何东西,您还需要给予 stdout=PIPE 和/或 stderr=PIPE

如果进程在 timeout 秒后没有终止,则会引发 TimeoutExpired 异常。捕获此异常并重试通信将不会丢失任何输出。

如果超时过期,子进程不会被杀死,因此为了正确清理,一个行为良好的应用程序应该杀死子进程并完成通信:

proc = subprocess.Popen(...)
try:
    outs, errs = proc.communicate(timeout=15)
except TimeoutExpired:
    proc.kill()
    outs, errs = proc.communicate()

注解

读取的数据在内存中缓冲,因此如果数据大小较大或无限制,则不要使用此方法。

在 3.3 版更改: 加入 timeout

Popen.send_signal(signal)

向孩子发送信号 signal

注解

在Windows上,SIGTERM是 terminate() 的别名。 CTRL_C_EVENT和CTRL_BREAK_EVENT可发送到以包含 CREATE_NEW_PROCESS_GROUPcreationflags 参数启动的进程。

Popen.terminate()

停止孩子。在Posix操作系统上,该方法向子进程发送SIGTERM。在Windows上调用Win32 API函数 TerminateProcess() 来停止子进程。

Popen.kill()

杀死孩子。在Posix操作系统上,函数向孩子发送SIGKILL。在Windows上 kill()terminate() 的别名。

还提供以下属性:

Popen.args

args 参数被传递给 Popen - 一系列程序参数或单个字符串。

3.3 新版功能.

Popen.stdin

如果 stdin 参数是 PIPE,则此属性是 open() 返回的可写流对象。如果指定了 encodingerrors 参数或 universal_newlines 参数为 True,则流是文本流,否则是字节流。如果 stdin 参数不是 PIPE,则此属性为 None

Popen.stdout

如果 stdout 参数是 PIPE,则此属性是 open() 返回的可读流对象。从流读取提供来自子进程的输出。如果指定了 encodingerrors 参数或 universal_newlines 参数为 True,则流是文本流,否则是字节流。如果 stdout 参数不是 PIPE,则此属性为 None

Popen.stderr

如果 stderr 参数是 PIPE,则此属性是 open() 返回的可读流对象。从流读取提供从子进程的错误输出。如果指定了 encodingerrors 参数或 universal_newlines 参数为 True,则流是文本流,否则是字节流。如果 stderr 参数不是 PIPE,则此属性为 None

警告

使用 communicate() 而不是 .stdin.write.stdout.read.stderr.read 以避免由于任何其他OS管道缓冲区填充和阻塞子进程而导致的死锁。

Popen.pid

子进程的进程ID。

注意,如果将 shell 参数设置为 True,那么这是生成的shell的进程ID。

Popen.returncode

子返回代码,由 poll()wait() (并由 communicate() 间接设置)设置。 None 值指示进程尚未终止。

负值 -N 表示孩子被信号 N (仅POSIX)终止。

17.5.4. Windows Popen助手

STARTUPINFO 类和以下常量仅在Windows上可用。

class subprocess.STARTUPINFO

部分支持Windows STARTUPINFO 结构用于 Popen 创建。

dwFlags

确定在进程创建窗口时是否使用某些 STARTUPINFO 属性的位字段。

si = subprocess.STARTUPINFO()
si.dwFlags = subprocess.STARTF_USESTDHANDLES | subprocess.STARTF_USESHOWWINDOW
hStdInput

如果 dwFlags 指定 STARTF_USESTDHANDLES,则此属性是进程的标准输入句柄。如果未指定 STARTF_USESTDHANDLES,则标准输入的默认值为键盘缓冲区。

hStdOutput

如果 dwFlags 指定 STARTF_USESTDHANDLES,则此属性是进程的标准输出句柄。否则,将忽略此属性,标准输出的默认值为控制台窗口的缓冲区。

hStdError

如果 dwFlags 指定 STARTF_USESTDHANDLES,则此属性是进程的标准错误句柄。否则,将忽略此属性,标准错误的默认值为控制台窗口的缓冲区。

wShowWindow

如果 dwFlags 指定 STARTF_USESHOWWINDOW,则该属性可以是除 SW_SHOWDEFAULT 之外的 ShowWindow 函数的 nCmdShow 参数中可以指定的任何值。否则,将忽略此属性。

为此属性提供了 SW_HIDE。当 Popenshell=True 调用时使用。

17.5.4.1. 常量

subprocess 模块公开以下常量。

subprocess.STD_INPUT_HANDLE

标准输入设备。最初,这是控制台输入缓冲区,CONIN$

subprocess.STD_OUTPUT_HANDLE

标准输出设备。最初,这是活动控制台屏幕缓冲区,CONOUT$

subprocess.STD_ERROR_HANDLE

标准错误设备。最初,这是活动控制台屏幕缓冲区,CONOUT$

subprocess.SW_HIDE

隐藏窗口。另一个窗口将被激活。

subprocess.STARTF_USESTDHANDLES

指定 STARTUPINFO.hStdInputSTARTUPINFO.hStdOutputSTARTUPINFO.hStdError 属性包含附加信息。

subprocess.STARTF_USESHOWWINDOW

指定 STARTUPINFO.wShowWindow 属性包含附加信息。

subprocess.CREATE_NEW_CONSOLE

新进程有一个新的控制台,而不是继承其父级控制台(默认)。

subprocess.CREATE_NEW_PROCESS_GROUP

用于指定将创建新进程组的 Popen creationflags 参数。此标志对于在子进程上使用 os.kill() 是必需的。

如果指定了 CREATE_NEW_CONSOLE,则忽略此标志。

17.5.5. 较旧的高级API

在Python 3.5之前,这三个函数包括高级API到子进程。现在可以在许多情况下使用 run(),但大量现有代码调用这些函数。

subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False, timeout=None)

运行 args 描述的命令。等待命令完成,然后返回 returncode 属性。

这相当于:

run(...).returncode

(除了不支持 inputcheck 参数)

上面显示的参数只是最常见的参数。完整的函数签名在很大程度上与 Popen 构造函数相同 - 该函数将除 timeout 之外的所有提供的参数直接传递到该接口。

注解

不要在此功能中使用 stdout=PIPEstderr=PIPE。子进程将阻塞它是否生成足够的输出到管道以填充OS管道缓冲区,因为未从中读取管道。

在 3.3 版更改: 加入 timeout

subprocess.check_call(args, *, stdin=None, stdout=None, stderr=None, shell=False, timeout=None)

运行带参数的命令。等待命令完成。如果返回码为零,那么返回,否则提出 CalledProcessErrorCalledProcessError 对象将具有 returncode 属性中的返回代码。

这相当于:

run(..., check=True)

(除了不支持 input 参数)

上面显示的参数只是最常见的参数。完整的函数签名在很大程度上与 Popen 构造函数相同 - 该函数将除 timeout 之外的所有提供的参数直接传递到该接口。

注解

不要在此功能中使用 stdout=PIPEstderr=PIPE。子进程将阻塞它是否生成足够的输出到管道以填充OS管道缓冲区,因为未从中读取管道。

在 3.3 版更改: 加入 timeout

subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, encoding=None, errors=None, universal_newlines=False, timeout=None)

使用参数运行命令并返回其输出。

如果返回码非零,它会产生一个 CalledProcessErrorCalledProcessError 对象将具有 returncode 属性中的返回码和 output 属性中的任何输出。

这相当于:

run(..., check=True, stdout=PIPE).stdout

上面显示的参数只是最常见的参数。完整的函数签名在很大程度上与 run() 相同 - 大多数参数直接传递到该接口。但是,不支持明确传递 input=None 以继承父标准输入文件句柄。

默认情况下,此函数将以编码字节返回数据。输出数据的实际编码可以取决于被调用的命令,因此对文本的解码通常需要在应用级处理。

可以通过将 universal_newlines 设置为如上所述的 常用参数 中的 True 来覆盖该行为。

要捕获结果中的标准误差,请使用 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'

3.1 新版功能.

在 3.3 版更改: 加入 timeout

在 3.4 版更改: 添加了对 input 关键字参数的支持。

17.5.6. 使用 subprocess 模块替换旧功能

在本节中,“a变为b”表示b可以用作a的替换。

注解

如果无法找到执行的程序,则本节中的所有“a”函数都会失败(或多或少); “b”替换提高 OSError

此外,如果所请求的操作产生非零返回码,则使用 check_output() 的替换将与 CalledProcessError 失败。输出仍然可用作引发异常的 output 属性。

在以下示例中,我们假设相关函数已从 subprocess 模块导入。

17.5.6.1. 替换/bin/sh shell反引号

output=`mycmd myarg`

成为:

output = check_output(["mycmd", "myarg"])

17.5.6.2. 更换外壳管道

output=`dmesg | grep hda`

成为:

p1 = Popen(["dmesg"], stdout=PIPE)
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
p1.stdout.close()  # Allow p1 to receive a SIGPIPE if p2 exits.
output = p2.communicate()[0]

启动p2后的p1.stdout.close()调用很重要,以便p1在p1之前退出时接收SIGPIPE。

或者,对于可信输入,shell自己的管道支持仍可以直接使用:

output=`dmesg | grep hda`

成为:

output=check_output("dmesg | grep hda", shell=True)

17.5.6.3. 更换 os.system()

sts = os.system("mycmd" + " myarg")
# becomes
sts = call("mycmd" + " myarg", shell=True)

笔记:

  • 通常不需要通过shell调用程序。

一个更现实的例子看起来像这样:

try:
    retcode = call("mycmd" + " myarg", shell=True)
    if retcode < 0:
        print("Child was terminated by signal", -retcode, file=sys.stderr)
    else:
        print("Child returned", retcode, file=sys.stderr)
except OSError as e:
    print("Execution failed:", e, file=sys.stderr)

17.5.6.4. 更换 os.spawn 系列

P_NOWAIT示例:

pid = os.spawnlp(os.P_NOWAIT, "/bin/mycmd", "mycmd", "myarg")
==>
pid = Popen(["/bin/mycmd", "myarg"]).pid

P_WAIT示例:

retcode = os.spawnlp(os.P_WAIT, "/bin/mycmd", "mycmd", "myarg")
==>
retcode = call(["/bin/mycmd", "myarg"])

矢量示例:

os.spawnvp(os.P_NOWAIT, path, args)
==>
Popen([path] + args[1:])

环境示例:

os.spawnlpe(os.P_NOWAIT, "/bin/mycmd", "mycmd", "myarg", env)
==>
Popen(["/bin/mycmd", "myarg"], env={"PATH": "/usr/bin"})

17.5.6.5. 更换 os.popen()os.popen2()os.popen3()

(child_stdin, child_stdout) = os.popen2(cmd, mode, bufsize)
==>
p = Popen(cmd, shell=True, bufsize=bufsize,
          stdin=PIPE, stdout=PIPE, close_fds=True)
(child_stdin, child_stdout) = (p.stdin, p.stdout)
(child_stdin,
 child_stdout,
 child_stderr) = os.popen3(cmd, mode, bufsize)
==>
p = Popen(cmd, shell=True, bufsize=bufsize,
          stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)
(child_stdin,
 child_stdout,
 child_stderr) = (p.stdin, p.stdout, p.stderr)
(child_stdin, child_stdout_and_stderr) = os.popen4(cmd, mode, bufsize)
==>
p = Popen(cmd, shell=True, bufsize=bufsize,
          stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True)
(child_stdin, child_stdout_and_stderr) = (p.stdin, p.stdout)

返回代码处理如下翻译:

pipe = os.popen(cmd, 'w')
...
rc = pipe.close()
if rc is not None and rc >> 8:
    print("There were some errors")
==>
process = Popen(cmd, stdin=PIPE)
...
process.stdin.close()
if process.wait() != 0:
    print("There were some errors")

17.5.6.6. 更换 popen2 模块的功能

注解

如果popen2函数的cmd参数是字符串,则通过/bin/sh执行该命令。如果是列表,则直接执行命令。

(child_stdout, child_stdin) = popen2.popen2("somestring", bufsize, mode)
==>
p = Popen("somestring", shell=True, bufsize=bufsize,
          stdin=PIPE, stdout=PIPE, close_fds=True)
(child_stdout, child_stdin) = (p.stdout, p.stdin)
(child_stdout, child_stdin) = popen2.popen2(["mycmd", "myarg"], bufsize, mode)
==>
p = Popen(["mycmd", "myarg"], bufsize=bufsize,
          stdin=PIPE, stdout=PIPE, close_fds=True)
(child_stdout, child_stdin) = (p.stdout, p.stdin)

popen2.Popen3popen2.Popen4 基本上作为 subprocess.Popen 工作,除了:

  • 如果执行失败,Popen 引发异常。

  • capturestderr 参数将替换为 stderr 参数。

  • 必须指定 stdin=PIPEstdout=PIPE

  • popen2默认关闭所有文件描述符,但是你必须指定 close_fds=True with Popen 以保证在所有平台或过去的Python版本上的行为。

17.5.7. 传统Shell调用函数

此模块还从2.x commands 模块提供以下旧功能。这些操作隐式调用系统shell,并且上述关于安全性和异常处理一致性的保证都不对这些函数有效。

subprocess.getstatusoutput(cmd)

返回在shell中执行 cmd(status, output)

在具有 Popen.check_output() 的shell中执行字符串 cmd,并返回一个2元组 (status, output)。使用区域设置编码;有关详细信息,请参阅 常用参数 的说明。

从输出中去除尾部换行符。可以根据C函数 wait() 的规则来解释命令的退出状态。例:

>>> subprocess.getstatusoutput('ls /bin/ls')
(0, '/bin/ls')
>>> subprocess.getstatusoutput('cat /bin/junk')
(256, 'cat: /bin/junk: No such file or directory')
>>> subprocess.getstatusoutput('/bin/junk')
(256, 'sh: /bin/junk: not found')

可用性:POSIX & Windows

在 3.3.4 版更改: 添加Windows支持

subprocess.getoutput(cmd)

返回在shell中执行 cmd 的输出(stdout和stderr)。

getstatusoutput(),除了退出状态被忽略,返回值是一个包含命令输出的字符串。例:

>>> subprocess.getoutput('ls /bin/ls')
'/bin/ls'

可用性:POSIX & Windows

在 3.3.4 版更改: 添加Windows支持

17.5.8. 笔记

17.5.8.1. 在Windows上将参数序列转换为字符串

在Windows上,args 序列转换为可以使用以下规则(对应于MS C运行时使用的规则)进行解析的字符串:

  1. 参数由空格分隔,空格或空格或制表符。

  2. 由双引号括起来的字符串将被解释为单个参数,而不考虑其中包含的空格。引用的字符串可以嵌入参数中。

  3. 双引号前面加上反斜杠解释为文字双引号。

  4. 反斜杠按字面解释,除非它们紧跟在双引号之前。

  5. 如果反斜杠紧跟在双引号之前,则每对反斜杠都被解释为文字反斜杠。如果反斜杠的数量为奇数,则最后一个反斜杠转义为下一个双引号,如规则3所述。

参见

shlex

模块提供解析和转义命令行的功能。