python Subprocess 模块
Subprocess 介绍
subprocess 模块是 Python 标准库中的一个模块,用于管理子进程(子程序)。通过 subprocess 模块,可以在 Python 脚本中启动新的进程、连接到它们的输入/输出流以及获取它们的返回值。
Subprocess 主要功能
1. 执行外部命令:subprocess 允许你在 Python 脚本中执行系统命令或其他可执行文件。
2. 进程管理:你可以启动新的进程并与其交互,监视它们的状态以及等待它们的完成。
3. 输入/输出重定向:通过 subprocess,你能够重定向进程的标准输入、输出和错误流,实现和外部进程的交互。
subprocess.run()
subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, capture_output=False, shell=False, cwd=None, timeout=None, check=False, encoding=None, errors=None, text=None, env=None, universal_newlines=None, **other_popen_kwargs)
用途:执行命令并等待其完成。
返回值:CompletedProcess 对象,包含执行结果和输出。
CompletedProcess 对象方法:
args:执行的命令及其参数列表。
returncode:命令的返回状态码(0 表示成功)。
stdout:命令的标准输出(以字节或字符串形式,取决于参数)。
stderr:命令的标准错误输出(以字节或字符串形式,取决于参数)。
check_returncode(): 命令的状态码,如果 returncode 非零, 抛出 CalledProcessError.
参数:
args:一个字符串列表,表示要执行的命令及其参数。例如:['ls', '-l']。
stdin, input:用于指定子进程的标准输入。如果 stdin 参数被设置为 subprocess.PIPE,则可以向子进程写入数据。input 参数用于向子进程提供输入数据。
stdout, stderr:用于指定子进程的标准输出和错误输出。这些参数可以是 subprocess.PIPE(用于捕获输出),或者是文件对象(用于将输出重定向到文件)。
capture_output:一个布尔值,用于决定是否捕获子进程的标准输出和错误输出。默认为 False。如果设置为 True,则 stdout 和 stderr 参数会被忽略,输出会被捕获并返回为字节串(如果 text 参数为 True,则为字符串)。
shell:一个布尔值,用于指示是否通过 shell 执行命令。默认为 False。如果设置为 True,则命令会由 shell 解析,这可能会带来安全风险(因为可能受到命令注入攻击)。
cwd:一个字符串,指定子进程的当前工作目录。默认为当前工作目录。
timeout:一个浮点数,指定命令执行的最长时间(秒)。如果命令运行时间超过这个时间,子进程会被终止。
check:一个布尔值,用于指示是否检查命令的退出状态码。如果设置为 True 且命令返回非零退出状态码,会抛出一个 CalledProcessError 异常。
encoding 和 errors:这两个参数用于处理输出的文本编码问题。如果 capture_output 或 text 参数为 True,则使用这些参数来解码字节输出。
text:一个布尔值,用于指示是否以文本模式运行子进程。与 capture_output 参数结合使用,如果两者都为 True,则输出将被捕获并作为字符串返回。默认为 None(根据 Python 版本和平台自动推断)。
env:一个字典,用于指定子进程的环境变量。默认使用父进程的环境变量。
示例
import subprocess
try:
result = subprocess.run(['ping', 'www.baidu.com' ], capture_output=True, text=True, check=True)
print(1, result.stdout)
print(2, result.returncode)
print(3, result.stderr)
print(4, result.args)
print(5, result.check_returncode())
except subprocess.CalledProcessError as e:
print(f"Error: {e.stderr}") # 输出错误信息
输出:
1
正在 Ping www.a.shifen.com [110.242.68.4] 具有 32 字节的数据:
来自 110.242.68.4 的回复: 字节=32 时间=15ms TTL=53
来自 110.242.68.4 的回复: 字节=32 时间=11ms TTL=53
来自 110.242.68.4 的回复: 字节=32 时间=12ms TTL=53
来自 110.242.68.4 的回复: 字节=32 时间=11ms TTL=53
110.242.68.4 的 Ping 统计信息:
数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 11ms,最长 = 15ms,平均 = 12ms
2 0
3
4 ['ping', 'www.baidu.com']
5 None
subprocess.Popen()
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=None, startupinfo=None, creationflags=0, restore_signals=True, start_new_session=False, pass_fds=(), *, group=None, extra_groups=None, user=None, umask=-1, encoding=None, errors=None, text=None, pipesize=-1, process_group=None)
用途:启动子进程,支持非阻塞执行和灵活的输入输出处理。
参数:
args: 一个包含命令和命令参数的列表(例如 ['ls', '-l'])。
bufsize: I/O缓冲策略,默认是-1表示使用系统默认缓冲。
executable: 如果指定了shell=True,这个参数用来指定shell的路径。
stdin, stdout, stderr: 分别代表子进程的标准输入、输出和错误流。默认是None,表示继承父进程的标准流。可以通过管道连接它们以实现数据通信。
preexec_fn: 在子进程启动之前执行的函数。通常用于设置环境变量或修改进程属性。
close_fds: 如果为True,关闭文件描述符(默认开启)。通常是为了安全考虑。
shell: 如果为True,使用shell来执行命令(有安全风险)。
cwd: 子进程的当前工作目录。如果不指定,则使用父进程的当前工作目录。
env: 一个字典,用于定义子进程的环境变量。如果不指定,则使用父进程的环境变量。
universal_newlines: 如果为True,使用文本模式进行文件读写(Python 3中默认是True)。
startupinfo 和 creationflags: 与Windows平台相关,用于配置子进程的启动信息和创建标志。
restore_signals: 是否恢复原始信号处理程序(在Unix平台上)。默认是True。
start_new_session: 如果为True并且平台支持,新进程会创建新的会话(用于控制终端窗口等)。
pass_fds: 一个文件描述符列表,这些描述符会被传递到子进程(仅适用于Unix平台)。用于文件描述符的复用通信。
group, extra_groups, user, umask: 这些参数用于设置子进程的权限和组属性(主要在Unix平台上)。
encoding 和 errors: 用于指定子进程的文本编码方式和处理错误的策略。仅在universal_newlines=True时有效。如果未指定,则使用默认编码方式处理错误。
Popen 类的实例拥有方法:
communicate(input=None, timeout=None):
与进程交互:将数据发送到 stdin。 从 stdout 和 stderr 读取数据,直到抵达文件结尾。 等待进程终止并设置 returncode 属性。 可选的 input 参数应为要发送到下级进程的数据,或者如果没有要发送到下级进程的数据则为 None。 如果流是以文本模式打开的,则 input 必须为字符串。 在其他情况下,它必须为字节串。
communicate() 返回一个 (stdout_data, stderr_data) 元组。如果文件以文本模式打开则为字符串;否则字节。
timeout 设置超时时间(单位为秒)。
wait(timeout=None):
等待子进程被终止。设置并返回 returncode 属性。
poll():
检查子进程的状态。返回子进程的退出码,如果子进程仍在运行则返回 None。
terminate():
发送 SIGTERM 信号以终止子进程。
kill():
发送 SIGKILL 信号以强制终止子进程。
send_signal(signal):
向子进程发送指定的信号。
args:
args 参数传递给 Popen -- 一个程序参数的序列或者一个简单字符串。
pid:
子进程的进程号。
returncode:
子进程的返回码。 初始为 None
stdout
如果 stdout 参数为 PIPE,此属性是一个类似 open() 所返回对象的可读流对象。 从流中读取将会提供来自子进程的输出。 如果 encoding 或 errors 参数被指定或者 text 或 universal_newlines 参数为 True,则这个流将是一个文本流,否则将是一个字节流。 如果 stdout 参数不为 PIPE,则此属性将为 None。
stderr
如果 stderr 参数为 PIPE,此属性是一个类似 open() 所返回对象的可读流对象。 从流中读取将会提供来自子进程的错误输出。 如果 encoding 或 errors 参数被指定或者 text 或 universal_newlines 参数为 True,则这个流将是一个文本流,否则将是一个字节流。 如果 stderr 参数不为 PIPE,则此属性将为 None。
stdin
如果 stdin 参数为 PIPE,此属性是一个类似 open() 所返回对象的可写流对象。 如果指定了 encoding 或 errors 参数或者 text 或 universal_newlines 参数为 True,则这个流将是一个文本流,否则将是一个字节流。 如果 stdin 参数不为 PIPE,则此属性将为 None。
示例
import subprocess
try:
result = subprocess.Popen(['ping', 'www.baidu.com' ], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
# 获取输出
stdout, stderr = result.communicate()
print(1, stdout)
print(2, stderr)
# 检查返回码
print("返回码:", result.returncode)
except TimeoutExpired:
proc.kill()
outs, errs = proc.communicate()
输出结果
F:\work\python\venv\devops\python.exe F:\work\python\project\gitlab\test.py
1
正在 Ping www.a.shifen.com [110.242.68.3] 具有 32 字节的数据:
来自 110.242.68.3 的回复: 字节=32 时间=12ms TTL=53
来自 110.242.68.3 的回复: 字节=32 时间=11ms TTL=53
来自 110.242.68.3 的回复: 字节=32 时间=11ms TTL=53
来自 110.242.68.3 的回复: 字节=32 时间=10ms TTL=53
110.242.68.3 的 Ping 统计信息:
数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 10ms,最长 = 12ms,平均 = 11ms
2
返回码: 0
进程已结束,退出代码0
subprocess.call()
在 Python 3.5 之后建议使用 run().
subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False, cwd=None, timeout=None, **other_popen_kwargs)
用途:运行由 args 所描述的命令。 等待命令完成,然后返回 returncode 属性。
参数:
args:一个字符串列表或字符串,代表要执行的命令和参数。
stdin, stdout, stderr:可选参数,用于指定子进程的标准输入、输出和错误输出。可以是文件对象、PIPE(用于与父进程通信)或其他合法的参数。如果不指定,通常使用默认值。
shell:一个布尔值,默认为 False。如果设置为 True,则命令将在 shell 中执行,这可能会带来安全风险(因为可能受到命令注入攻击)。通常不建议使用 shell=True。
cwd:可选参数,指定子进程的当前工作目录。
timeout:可选参数,设置命令执行的最大时间(秒)。如果超过这个时间,子进程会被杀死。
**other_popen_kwargs:其他可选的关键字参数,用于传递给底层的 Popen 类。
示例
import subprocess
process = subprocess.call(['ping', 'www.baidu.com'], stdout=subprocess.DEVNULL)
print(process) # 输出: 0
subprocess.check_call()
在 Python 3.5 之后建议使用 run().
subprocess.check_call(args, *, stdin=None, stdout=None, stderr=None, shell=False, cwd=None, timeout=None, **other_popen_kwargs)
用途:附带参数运行命令。 等待命令完成。 如果返回码为零则正常返回,否则引发 CalledProcessError。 CalledProcessError 对象将在 returncode 属性中保存返回码。
参数:
args: 一个字符串列表,表示要执行的命令及其参数。例如:['ls', '-l']。这是必需的参数。
stdin, stdout, stderr: 这些参数用于指定子进程的标准输入、标准输出和标准错误输出。它们可以是 subprocess.PIPE(用于捕获输出),也可以是文件对象(用于重定向输出到文件)。如果不指定这些参数,子进程将继承父进程的标准输入、输出和错误流。
shell: 一个布尔值,指示是否通过 shell 执行命令。默认为 False。如果设置为 True,则命令会由 shell 解析,这可能会带来安全风险(因为可能受到命令注入攻击)。通常不建议使用此参数,除非确实需要 shell 功能(如使用管道或重定向)。
cwd: 一个字符串,指定子进程的当前工作目录。默认为当前工作目录。
timeout: 一个浮点数,指定命令执行的最长时间(秒)。如果命令运行时间超过这个时间,子进程会被终止。这是一个可选参数。
**other_popen_kwargs: 其他可以传递给 Popen 构造函数的参数。这些参数允许你自定义子进程的创建和行为。
示例
import subprocess
process = subprocess.check_call(['ping', 'www.baidu.com'], stdout=subprocess.DEVNULL)
print(process) # 输出: 0
subprocess.check_output()
在 Python 3.5 之后建议使用 run().
subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, cwd=None, encoding=None, errors=None, universal_newlines=None, timeout=None, text=None, **other_popen_kwargs)
用途:附带参数运行命令并返回其输出。
参数:
args:一个字符串列表,表示要执行的命令及其参数。例如:['ls', '-l']。
stdin:可选参数,用于指定子进程的标准输入。通常不需要设置。
stderr:可选参数,用于指定子进程的错误输出。默认不捕获错误输出。
shell:布尔值,指示是否通过 shell 执行命令。默认为 False。设置为 True 时需注意安全风险,因为可能受到命令注入攻击。
cwd:可选参数,指定子进程的当前工作目录。
encoding:可选参数,用于指定输出字符串的编码方式。如果不指定,输出将是字节串。
errors:可选参数,指定处理编码错误的策略。
universal_newlines:(不推荐使用,建议使用 text 参数)如果为 True,则输出将是文本模式,与 encoding 参数配合使用。
timeout:可选参数,指定命令执行的最长时间(秒)。超过这个时间会终止进程并抛出异常。
text:布尔值,指示是否以文本模式启动子进程(建议使用这个参数替代 universal_newlines)。
**other_popen_kwargs:其他可选的关键字参数,用于传递给底层的 Popen 类。
示例
import subprocess
process = subprocess.check_output(['ping', 'www.baidu.com'], text=True)
print(process)
输出结果
正在 Ping www.a.shifen.com [110.242.68.4] 具有 32 字节的数据:
来自 110.242.68.4 的回复: 字节=32 时间=19ms TTL=53
来自 110.242.68.4 的回复: 字节=32 时间=12ms TTL=53
来自 110.242.68.4 的回复: 字节=32 时间=14ms TTL=53
来自 110.242.68.4 的回复: 字节=32 时间=22ms TTL=53
110.242.68.4 的 Ping 统计信息:
数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 12ms,最长 = 22ms,平均 = 16ms
参考文档
https://docs.python.org/3/library/subprocess.html