探索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模块可用于自动化各种系统任务,例如运行备份、启动和停止服务以及计划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 Subprocess模块可以帮助您运行其他语言(如Perl、Ruby和Bash)编写的脚本。例如,您可以使用Python Subprocess模块运行执行特定任务的Perl脚本,然后在自己的代码中使用该脚本的输出。这对于数据处理、文本操作和系统管理非常有用。
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 .
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
...
示例 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)
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.
请注意,命令失败是因为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模块提供了创建和与子进程交互的方式,可用于运行其他程序或命令。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模块时,可能会遇到一些常见问题。以下是一些常见问题的解决方法:
问题 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官方文档以获取更多信息,并尝试不同的参数和选项来调试和解决问题。