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

posted @ 2024-07-24 13:49  小吉猫  阅读(73)  评论(0编辑  收藏  举报