• Python Subprocess介绍:基础和示例


    Python Subprocess介绍:基础和示例

    探索Python Subprocess模块的逐步指南,包括示例。

    目录


    什么是 Python Subprocess

    Python Subprocess模块是一种工具,允许您从Python代码中运行其他程序或命令。它可以用于启动新程序、向它们发送数据并获取结果。

    它就像是使用Python而不是直接在命令提示符中键入命令来向计算机发出命令。该模块使得自动化任务和将其他程序与Python代码集成变得容易。

    例如,您可以使用Python Subprocess模块在Python代码中运行shell命令(如“ls”或“ping”),并获取该命令的输出。您还可以使用它来运行其他Python脚本或在Windows上运行.exe文件。

    此外,Python Subprocess模块可以重定向进程的输入和输出,这意味着您可以控制发送到进程的数据以及从中接收的数据。

    Python Subprocess模块最有用的功能之一是它允许用户从Python代码内部处理子进程生成的输入、输出甚至错误。这一功能被认为是该模块最强大的方面之一。由于这一功能,现在可以使调用子进程的过程更加强大和多功能。例如,现在可以在Python脚本的其余部分中使用子进程的输出作为变量。

    在本教程中,我们将学习如何使用Python Subprocess模块在Python代码中运行其他程序,如何向它们发送数据以及如何获取结果。无论您是初学者还是经验丰富的Python开发人员,本教程都将为您提供在项目中有效使用Python Subprocess模块所需的知识。


    何时使用 Python Subprocess

    自动化系统任务

    Python Subprocess模块可用于自动化各种系统任务,例如运行备份、启动和停止服务以及计划cron作业。例如,您可以使用Python Subprocess模块运行“cp”命令以创建文件的备份,或者使用“service”命令在Linux系统上启动和停止服务。

    您还可以使用Python Subprocess模块使用cron或其他调度工具安排在特定时间间隔运行任务。

    运行命令行工具

    Python Subprocess模块可用于运行命令行工具,如grep、sed和awk,并在Python代码中处理其输出。例如,您可以使用Python Subprocess模块运行“grep”命令以在文件中搜索特定模式,然后在Python代码中处理输出。这对于日志分析、数据处理和文本操作等任务非常有用。

    运行外部可执行文件

    Python Subprocess模块可以运行其他可执行文件,如Windows上的.exe文件,并控制其行为。例如,您可以使用Python Subprocess模块运行执行特定任务的可执行文件,然后在自己的代码中使用该可执行文件的输出。这对于图像处理、数据分析和机器学习任务非常有用。

    作为后台进程运行脚本

    您可以使用Python Subprocess模块将脚本作为后台进程运行,以便它们在主程序退出后继续运行。例如,您可以使用Python Subprocess模块运行执行特定任务的脚本,并在主程序退出而不等待脚本完成。这对于监控、日志记录和数据收集非常有用。

    使用非Python解释器运行脚本

    Python Subprocess模块可以帮助您运行其他语言(如Perl、Ruby和Bash)编写的脚本。例如,您可以使用Python Subprocess模块运行执行特定任务的Perl脚本,然后在自己的代码中使用该脚本的输出。这对于数据处理、文本操作和系统管理非常有用。

    并行处理

    Python Subprocess模块可用于并行运行多个进程,这对于图像处理、数据分析和机器学习等任务非常有用。例如,您可以使用Python Subprocess模块运行多个相同脚本的实例,每个实例处理数据的不同部分,然后合并结果。


    Python Subprocess示例

    使用 subprocess.run

    subprocess.run()方法是运行子进程并等待其完成的便捷方式。它允许您选择要运行的命令并添加选项,如参数、环境变量和输入/输出重定向。一旦启动子进程,run()方法会阻塞,直到子进程完成,并返回一个CompletedProcess对象,其中包含子进程的返回码和输出。

    subprocess.run()方法接受多个参数,其中一些是:

    • args:要运行的命令及其参数,以字符串列表形式传递。
    • capture_output:当设置为True时,将捕获标准输出和标准错误。
    • text:当设置为True时,将以字符串形式返回stdout和stderr,否则返回字节形式。
    • check:一个布尔值,指示是否检查子进程的返回码。如果check为True且返回码为非零,则引发CalledProcessError异常。
    • timeout:以秒为单位指定子进程完成前等待的时间。
    • shell:一个布尔值,指示是否在shell中运行命令。这意味着命令将作为字符串传递,并且可以使用shell特定的功能,如通配符扩展和变量替换。

    subprocess.run()方法还返回一个CompletedProcess对象,其中包含以下属性:

    • args:运行的命令和参数。
    • returncode:子进程的返回码。
    • stdout:子进程的标准输出,以字节对象形式。
    • stderr:子进程的标准错误,以字节对象形式。

    示例 1:运行shell命令

    import subprocess
    
    result = subprocess.run(["dir"], shell=True, capture_output=True, text=True)
    
    print(result.stdout)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    输出:

    Volume in drive C has no label.
    
    Volume Serial Number is E414-A41C
    
     Directory of C:\Users\owner
    
    01/25/2023  10:56 AM              .
    
    01/25/2023  10:56 AM              ..
    
    07/19/2021  01:19 PM              .anaconda
    
    07/19/2021  01:19 PM              .astropy
    
    07/19/2021  01:19 PM              .aws
    
    09/12/2022  08:48 AM               496 .bash_history
    
    03/27/2022  03:08 PM              .cache
    
    09/26/2021  06:58 AM              .conda
    
    09/26/2021  06:59 AM                25 .condarc
    ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    示例 2:运行Python脚本

    您还可以使用subprocess.run()方法运行Python脚本。首先,创建一个简单的Python脚本保存为.py文件:

    print("This is the output from subprocess module")
    
    • 1

    现在,可以使用subprocess模块来运行这个脚本:

    import subprocess
    
    result = subprocess.run(["python", "my_python_file.py"], capture_output=True, text=True)
    
    print(result.stdout)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    输出:

    This is the output from subprocess module
    
    • 1

    示例 3:直接从函数中运行Python代码

    对于简单的用例,您可以直接将Python命令传递给subprocess.run()函数。例如:

    result = subprocess.run(["C:/Users/owner/anaconda3/python", "-c", "print('This is directly from a subprocess.run() function')"], capture_output=True, text=True)
    
    print(result.stdout)
    
    • 1
    • 2
    • 3

    输出:

    This is directly from a subprocess.run() function
    
    • 1

    在参数列表中,第一个元素C:/Users/owner/anaconda3/python是可执行Python的路径(您的路径可能不同)。第二个元素-c是一个Python标记,允许用户将Python代码以文本形式传递给命令行。第三个元素print(...)是Python命令本身。

    示例 4:使用check参数

    check参数是Python subprocess模块中subprocess.run()函数的一个可选参数。它是一个布尔值,控制是否应检查正在运行的命令的返回码。

    check设置为True时,函数将检查命令的返回码,如果返回码为非零,则引发CalledProcessError异常。异常将具有返回码、stdout、stderr和命令作为属性。

    check设置为False(默认值)时,函数不会检查返回码,即使命令失败也不会引发异常。

    示例:使用check参数

    import subprocess
    
    result = subprocess.run(["python", "file_donot_exist.py"], capture_output=True, text=True, check=True)
    
    print(result.stdout)
    
    print(result.stderr)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    输出:

    ---------------------------------------------------------------------------
    
    CalledProcessError                        Traceback (most recent call last)
    
     in 
    
          1 import subprocess
    
    ----> 2 result = subprocess.run(["python", "file_donot_exist.py"], capture_output=True, text=True, check=True)
    
          3 print(result.stdout)
    
          4 print(result.stderr)
    
    ~\anaconda3\lib\subprocess.py in run(input, capture_output, timeout, check, *popenargs, **kwargs)
    
        514         retcode = process.poll()
    
        515         if check and retcode:
    
    --> 516             raise CalledProcessError(retcode, process.args,
    
        517                                      output=stdout, stderr=stderr)
    
        518     return CompletedProcess(process.args, retcode, stdout, stderr)
    
    CalledProcessError: Command '['python', 'file_donot_exist.py']' returned non-zero exit status 2.
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    请注意,命令失败是因为file_donot_exist.py不存在。与设置check=True不同,您的进程不会失败;相反,您将在stdout中获取错误消息。


    使用 subprocess.Popen

    subprocess.Popen是运行子进程的较低级接口,而subprocess.run是Popen的高级封装,旨在更方便使用。

    Popen允许您启动一个新的进程并与其标准输入、输出和错误流进行交互。它返回一个对正在运行的进程的句柄,可以用于等待进程完成、检查其返回码或

    终止它。

    run是一个更方便的函数,允许您运行一个命令并在单个调用中捕获其输出,而无需创建Popen对象并自己管理流。它还允许您指定运行命令的各种选项,例如是否在命令失败时引发异常。

    一般来说,如果您只需要运行命令并捕获其输出,那么应使用run;如果您需要更多对进程的控制,如与其输入和输出流交互,则应使用Popen

    Popen类接受与run()相同的参数,包括指定要运行的命令的args和其他可选参数,如stdin、stdout、stderr、shell、cwd和env。

    Popen类有几种方法,允许您与进程进行交互,例如communicate()、poll()、wait()、terminate()和kill()。

    示例:使用 subprocess.Popen

    import subprocess
    
    p = subprocess.Popen(["python", "--help"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
    
    output, errors = p.communicate()
    
    print(output)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    输出:

    usage: python [option] ... [-c cmd | -m mod | file | -] [arg] ...
    
    Options and arguments (and corresponding environment variables):
    
    -b     : issue warnings about str(bytes_instance), str(bytearray_instance)
    
             and comparing bytes/bytearray with str. (-bb: issue errors)
    
    -B     : don't write .pyc files on import; also PYTHONDONTWRITEBYTECODE=x
    
    -c cmd : program passed in as string (terminates option list)
    
    -d     : debug output from parser; also PYTHONDEBUG=x
    
    -E     : ignore PYTHON* environment variables (such as PYTHONPATH)
    ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    这将运行命令python –help并创建一个新的Popen对象,将其存储在变量p中。使用communicate()方法捕获命令的标准输出和错误,并将其分别存储在变量output和errors中。

    subprocess.Popen在您想要更多地控制进程时非常有用,比如向它发送输入、从中接收输出或等待其完成。


    使用 subprocess.call

    subprocess.call()是Python subprocess模块中的一个函数,用于在单独的进程中运行命令并等待其完成。它返回命令的返回码,如果命令成功,则返回码为零,否则为非零。

    call()函数接受与run()相同的参数,包括指定要运行的命令的args和其他可选参数,如stdin、stdout、stderr、shell、cwd和env。

    命令的标准输出和错误将发送到与父进程相同的stdout和stderr,除非使用stdout和stderr参数重定向它们。

    示例:使用 subprocess.call

    import subprocess
    
    return_code = subprocess.call(["python", "--version"])
    
    if return_code == 0:
        print("Command executed successfully.")
    else:
        print("Command failed with return code", return_code)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    输出:

    Command executed successfully.
    
    • 1

    这将在单独的进程中运行命令python –version并等待其完成。命令的返回码将存储在return_code变量中,如果命令成功,则为零,否则为非零。

    subprocess.call()在您想要运行命令并检查返回码,但不需要捕获输出时非常有用。


    使用 subprocess.check_output

    check_output是subprocess模块中的一个函数,类似于run(),但它仅返回命令的标准输出,并且如果返回码为非零,则引发CalledProcessError异常。

    check_output函数接受与run()相同的参数,包括指定要运行的命令的args和其他可选参数,如stdin、stderr、shell、cwd和env。

    check_output函数将命令的标准输出作为字节对象或字符串返回,如果传递了text=True,则返回字符串。

    示例:使用 subprocess.check_output

    import subprocess
    
    try:
        output = subprocess.check_output(["python", "--version"], text=True)
        print(output)
    except subprocess.CalledProcessError as e:
        print(f"Command failed with return code {e.returncode}")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    输出:

    Python 3.8.8
    
    • 1

    check_output函数将命令python --version的标准输出返回为字符串,并在命令失败时引发异常。


    Python Subprocess管道

    Python subprocess模块提供了创建和与子进程交互的方式,可用于运行其他程序或命令。subprocess模块的一个特性是能够创建管道,允许父进程与子进程之间进行通信。

    管道是一种单向通信通道,将一个进程的标准输出连接到另一个进程的标准输入。管道可以使用subprocess模块

    中的Popen对象来创建。在创建管道时,您可以指定输入和输出的处理方式。

    以下是一个示例,演示如何在Python中创建和使用管道:

    import subprocess
    
    # 创建一个子进程,它的标准输出将成为管道的输入
    process1 = subprocess.Popen(["echo", "Hello, World!"], stdout=subprocess.PIPE, text=True)
    
    # 创建另一个子进程,它的标准输入将连接到管道的输出
    process2 = subprocess.Popen(["grep", "Hello"], stdin=process1.stdout, stdout=subprocess.PIPE, text=True)
    
    # 读取process2的标准输出
    output = process2.communicate()[0]
    
    # 打印结果
    print(output)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在这个示例中,首先创建一个子进程process1,它执行echo "Hello, World!"命令,并将标准输出连接到管道。然后,创建另一个子进程process2,它执行grep "Hello"命令,并将标准输入连接到管道的输出。最后,使用communicate()方法读取process2的标准输出并打印结果。

    通过使用管道,您可以将多个子进程链接在一起,以实现更复杂的数据处理和流程控制。


    结论

    Python Subprocess模块是Python标准库中的一个有用工具,允许您在Python代码中运行其他程序或命令,以及与它们进行交互。它在自动化系统任务、运行命令行工具、运行外部可执行文件、作为后台进程运行脚本、使用非Python解释器运行脚本和并行处理等方面非常有用。

    在本教程中,我们介绍了如何使用Python Subprocess模块的不同函数和方法来运行命令、捕获输出以及与子进程进行交互。无论您是初学者还是有经验的Python开发人员,掌握Python Subprocess模块将增加您的工作效率并扩展您的应用程序的功能。

    如果您有任何疑问或需要更多帮助,可以参考Python官方文档中的Subprocess模块部分,以获得更多详细信息。


    Python Subprocess常见问题

    在使用Python Subprocess模块时,可能会遇到一些常见问题。以下是一些常见问题的解决方法:

    问题 1:为什么我的子进程没有启动?

    如果您的子进程没有启动,可能有几个原因。首先,请确保您提供了正确的命令和参数。还要检查是否设置了正确的工作目录(cwd)和环境变量(env)。如果您在Windows上运行命令,还要确保shell参数设置为True,以便在shell中执行命令。

    问题 2:如何捕获子进程的标准错误?

    要捕获子进程的标准错误,可以在创建子进程时将stderr=subprocess.PIPE传递给Popen构造函数。然后,您可以使用communicate()方法获取标准错误的输出。例如:

    import subprocess
    
    process = subprocess.Popen(["my_command"], stderr=subprocess.PIPE, text=True)
    output, errors = process.communicate()
    
    • 1
    • 2
    • 3
    • 4

    问题 3:如何处理非零的返回码?

    如果子进程返回了非零的返回码,您可以通过检查returncode属性来判断命令是否成功。如果命令失败,您可以进一步处理错误或采取适当的措施。例如:

    import subprocess
    
    process = subprocess.run(["my_command"])
    if process.returncode != 0:
        print("Command failed with return code", process.returncode)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    这些是一些常见问题的解决方法,但在使用Python Subprocess模块时可能会遇到其他问题。在遇到问题时,建议查看Python官方文档以获取更多信息,并尝试不同的参数和选项来调试和解决问题。

  • 相关阅读:
    Rabbit加密算法:性能与安全的完美结合
    52 杨辉三角
    2019CCF非专业级别软件能力认证第一轮
    redis 配置与优化
    Java-day13(IO流)
    Verilog中 generate语句的用法
    基于Echarts实现可视化数据大屏车辆类型統计
    1688图片搜索商品接口(以图搜索商品接口)代码对接教程
    长安汽车董事长下场宣传原力技术 全擎引领电动化出行普及时代
    1796. 字符串中第二大的数字
  • 原文地址:https://blog.csdn.net/Geek_/article/details/133129299