Python Subprocess介绍:基础和示例

2023-09-21 11:23:53

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)

输出:

Volume in drive C has no label.

Volume Serial Number is E414-A41C

 Directory of C:\Users\owner

01/25/2023  10:56 AM    <DIR>          .

01/25/2023  10:56 AM    <DIR>          ..

07/19/2021  01:19 PM    <DIR>          .anaconda

07/19/2021  01:19 PM    <DIR>          .astropy

07/19/2021  01:19 PM    <DIR>          .aws

09/12/2022  08:48 AM               496 .bash_history

03/27/2022  03:08 PM    <DIR>          .cache

09/26/2021  06:58 AM    <DIR>          .conda

09/26/2021  06:59 AM                25 .condarc
...

示例 2:运行Python脚本

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

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

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

import subprocess

result = subprocess.run(["python", "my_python_file.py"], capture_output=True, text=True)

print(result.stdout)

输出:

This is the output from subprocess module

示例 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)

输出:

This is directly from a subprocess.run() function

在参数列表中,第一个元素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)

输出:

---------------------------------------------------------------------------

CalledProcessError                        Traceback (most recent call last)

<ipython-input-81-503b60184db8> in <module>

      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.

请注意,命令失败是因为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)

输出:

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)
...

这将运行命令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)

输出:

Command executed successfully.

这将在单独的进程中运行命令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}")

输出:

Python 3.8.8

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)

在这个示例中,首先创建一个子进程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()

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

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

import subprocess

process = subprocess.run(["my_command"])
if process.returncode != 0:
    print("Command failed with return code", process.returncode)

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

更多推荐

后端中间件安装与启动(Redis、Nginx、Nacos、Kafka)

后端中间件安装与启动RedisNginxNacosKafkaRedis1.打开cmd终端,进入redis文件目录2.输入redis-server.exeredis.windows.conf即可启动,不能关闭cmd窗口(端口配置方式:redis目录下的redis.windows.conf配置文件,打开文件,修改NETWO

从零开始训练大模型

Task05从零开始训练大模型目录1.预训练阶段1.1TokenizerTraining1.2LanguageModelPreTraining1.3数据集清理1.4模型效果评测2.指令微调阶段(InstructionTuningStage)2.1SelfInstruction2.2开源数据集整理2.3模型的评测方法3.

C++之容器std::queue类empty、size、front、back、push、emplace、pop、swap应用总结(二百二十四)

简介:CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长!优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀人生格言:人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.更多原创,欢迎关注:Android系统攻城狮1.前言本篇目的:C++之

【云原生】kubernetes中pod(进阶)

目录一、资源限制业务cpu内存1.1CPU资源单位1.2内存资源单位示例1示例2:二、健康检查:又称为探针(Probe)2.1探针的三种规则2.2Probe支持三种检查方法2.3示例示例1:exec方式示例3:tcpSocket方式示例4:就绪检测示例5:就绪检测2示例:启动、退出动作扩展pod的状态Container

Element树形控件使用过程中遇到的问题及解决方法

1.需求1点击编辑按钮,出现修改组织弹窗,且将点击时的组织名称返现在输入框中。思路是点击编辑按钮,取到节点点击时返回的data信息中的label进行赋值即可。<el-treestyle="margin-top:20px":data="organizationTreeData"node-key="id"default-e

mysql死锁排查及解决

MySQL死锁是在多个并发事务同时请求相同资源时发生的一种情况,其中每个事务都在等待对方释放资源,从而导致数据库无法继续执行。死锁的排查和解决通常需要以下步骤:1.检测死锁:MySQL通常会在错误日志中记录死锁信息。可以通过以下方式检测死锁:SHOWENGINEINNODBSTATUS;查找"InnoDB"部分,寻找"

Win10编译chrome

一、系统准备windows10以上版本硬盘空余空间100G以上,磁盘格式为NTFS内存8G以上,推荐32G需要科学上网卸载杀毒软件(注意重启系统)二、安装VisualStudio2022VisualStudio2022(>=17.0.0)编译chromium时需要VisualStudio的支持。在windows操作系统

Android Media3 ExoPlayer 开启缓存功能

ExoPlayer开启播放缓存功能,在下次加载已经播放过的网络资源的时候,可以直接从本地缓存加载,实现为用户节省流量和提升加载效率的作用。方法一:采用ExoPlayer缓存策略第1步:实现Exoplayer参考Exoplayer官网Releasenotes:对应关系:2.19.0(2023-07-05)--Androi

黑马JVM总结(十一)

(1)垃圾回收概述前面我们学了堆,里面有一个垃圾回收的机制(2)判断垃圾_引用计数指只要有一个对象被其他变量所引用,我们就让这个对象的计数加1,有个一变量不在引用,让它的计数减一,当这个对象的计数变为0的时候,说明没有变量引用它了,那么他就可以作为一个垃圾进行一个回收,但是引用计数存在一个弊端:存在循环引用问题:a对象

Pytorch实现MNIST字符识别

1.下载mnist.pkl.gz网址:http://www.iro.umontreal.ca/~lisa/deep/data/mnist/mnist.pkl.gz数据集文件夹路径是data2/mnist/mnist.pkl.gz2.读取数据frompathlibimportPathimportmatplotlib.py

设计模式:状态模式

目录组件代码示例源码中使用优缺点总结状态模式(StatePattern)是一种行为型设计模式,用于解决对象在不同状态下的行为变化问题。状态模式允许对象在内部状态发生改变时改变其行为,使得对象的行为可以根据状态的改变而灵活变化。在状态模式中,对象的行为会根据其内部状态的改变而变化,但对外部来说,对象的接口保持一致。状态模

热文推荐