Python Subprocess库详解

2024-02-05 16:57:26 浏览数 (1)

简介

Subprocess库是Python中用于创建和管理子进程的标准库。它提供了一个强大而灵活的接口,使得你可以在Python中启动新的进程、连接它们的输入和输出,并与它们进行交互。本教程将介绍Subprocess库的基本概念、用法和一些常见的应用场景。

安装

Subprocess库是Python标准库的一部分,因此无需额外安装。你可以直接在Python脚本中导入它:

代码语言:javascript复制
pythonCopy codeimport subprocess

subprocess.run()

subprocess.run()是Subprocess库的主要函数之一,它用于运行命令并等待其完成。以下是一个简单的例子:

代码语言:javascript复制
pythonCopy codeimport subprocess

result = subprocess.run(['ls', '-l'], stdout=subprocess.PIPE, text=True)
print(result.stdout)

在这个例子中,subprocess.run()接受一个命令列表(如'ls', '-l'),并返回一个CompletedProcess对象。在这个对象中,你可以访问命令的标准输出、标准错误、返回码等信息。

控制输入和输出

Subprocess库允许你将子进程的输入和输出与父进程进行交互。以下是一个简单的例子,演示如何向子进程发送输入,并从子进程获取输出:

代码语言:javascript复制
pythonCopy codeimport subprocess

input_data = "Hello, Subprocess!"
result = subprocess.run(['echo'], input=input_data, stdout=subprocess.PIPE, text=True)
print(result.stdout)

在这个例子中,subprocess.run()input参数用于将数据传递给子进程的标准输入。stdout=subprocess.PIPE表示将子进程的标准输出捕获到父进程。

处理错误

如果子进程返回非零的退出码,subprocess.run()将引发CalledProcessError异常。你可以使用check参数来控制是否引发异常:

代码语言:javascript复制
pythonCopy codeimport subprocess

try:
    subprocess.run(['ls', 'nonexistent'], check=True)
except subprocess.CalledProcessError as e:
    print(f"Error: {e}")

在这个例子中,由于'ls nonexistent'命令无法找到文件,将引发CalledProcessError异常。

使用Popen类

除了subprocess.run()外,Subprocess库还提供了subprocess.Popen类,它允许更细粒度地控制子进程的输入、输出和行为。以下是一个使用Popen的例子:

代码语言:javascript复制
pythonCopy codeimport subprocess

with subprocess.Popen(['ls', '-l'], stdout=subprocess.PIPE, text=True) as process:
    output, _ = process.communicate()
    print(output)

在这个例子中,Popen对象的communicate()方法用于等待子进程完成,并获取其输出。

高级用法

Subprocess库还提供了许多其他功能,如处理环境变量、设置工作目录、使用管道连接多个进程等。以下是一个使用管道连接两个进程的例子:

代码语言:javascript复制
pythonCopy codeimport subprocess

process1 = subprocess.Popen(['ls', '-l'], stdout=subprocess.PIPE, text=True)
process2 = subprocess.Popen(['grep', 'file'], stdin=process1.stdout, stdout=subprocess.PIPE, text=True)

output, _ = process2.communicate()
print(output)

在这个例子中,process1的标准输出被连接到process2的标准输入,从而实现了两个命令的联合执行。

超时处理

在实际应用中,我们可能希望设置子进程的最长运行时间,以避免因子进程无法正常退出而导致父进程一直等待。Subprocess库允许你通过timeout参数来设置超时时间:

代码语言:javascript复制
pythonCopy codeimport subprocess

try:
    result = subprocess.run(['sleep', '5'], timeout=3)
    print(result.returncode)
except subprocess.TimeoutExpired:
    print("Timeout expired")

在这个例子中,subprocess.run()timeout参数设置为3秒,因此如果子进程运行时间超过3秒,将引发TimeoutExpired异常。

使用Shell命令

有时候我们可能需要在子进程中执行Shell命令,而不是直接运行可执行文件。可以通过将shell参数设置为True来实现这一点:

代码语言:javascript复制
pythonCopy codeimport subprocess

result = subprocess.run('echo Hello, Subprocess!', shell=True, stdout=subprocess.PIPE, text=True)
print(result.stdout)

请注意,使用Shell命令可能会带来一些安全风险,应当谨慎使用。

重定向文件描述符

Subprocess库允许你重定向子进程的文件描述符,例如将标准错误输出到文件。以下是一个例子:

代码语言:javascript复制
pythonCopy codeimport subprocess

with open('output.txt', 'w') as output_file:
    result = subprocess.run(['ls', '-l', '/nonexistent'], stderr=output_file)
    print(result.returncode)

在这个例子中,标准错误输出被重定向到名为output.txt的文件中。

使用环境变量

你可以通过env参数传递环境变量给子进程。以下是一个例子:

代码语言:javascript复制
pythonCopy codeimport subprocess

custom_env = {'CUSTOM_VARIABLE': 'custom_value'}
result = subprocess.run(['echo', '$CUSTOM_VARIABLE'], env=custom_env, shell=True, stdout=subprocess.PIPE, text=True)
print(result.stdout)

在这个例子中,我们定义了一个自定义环境变量CUSTOM_VARIABLE,并将其传递给子进程。

使用管道进行进程间通信

Subprocess库允许你使用管道(pipes)进行进程间通信。这在需要将一个进程的输出传递给另一个进程时非常有用。以下是一个简单的例子:

代码语言:javascript复制
pythonCopy codeimport subprocess

process1 = subprocess.Popen(['echo', 'Hello, Subprocess!'], stdout=subprocess.PIPE, text=True)
process2 = subprocess.Popen(['grep', 'Subprocess'], stdin=process1.stdout, stdout=subprocess.PIPE, text=True)

output, _ = process2.communicate()
print(output)

在这个例子中,process1的标准输出被连接到了process2的标准输入,从而实现了两个进程的协同工作。

实时获取输出

有时候我们希望实时获取子进程的输出,而不是等到它完成。可以使用stdout=subprocess.PIPEstderr=subprocess.PIPE参数,并通过communicate()实时获取输出:

代码语言:javascript复制
pythonCopy codeimport subprocess

process = subprocess.Popen(['ping', 'example.com'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)

while True:
    output = process.stdout.readline()
    if output == '' and process.poll() is not None:
        break
    if output:
        print(output.strip())

# 获取子进程的错误输出
error_output, _ = process.communicate()
print(error_output)

在这个例子中,我们使用stdout=subprocess.PIPEstderr=subprocess.PIPE参数将子进程的标准输出和标准错误输出捕获到父进程,然后通过循环实时读取输出。

使用Subprocess执行外部命令

Subprocess库还提供了一个名为subprocess.call()的函数,用于执行外部命令。它类似于subprocess.run(),但没有CompletedProcess对象的返回:

代码语言:javascript复制
pythonCopy codeimport subprocess

return_code = subprocess.call(['ls', '-l'])
print(return_code)

在这个例子中,subprocess.call()执行了ls -l命令,返回了命令的退出码。

使用Subprocess处理非文本数据

如果你需要处理非文本数据,可以将text参数设置为False,并使用subprocess.PIPE捕获二进制输出:

代码语言:javascript复制
pythonCopy codeimport subprocess

process = subprocess.Popen(['cat', 'binary_file'], stdout=subprocess.PIPE, text=False)

binary_output, _ = process.communicate()
with open('output.bin', 'wb') as output_file:
    output_file.write(binary_output)

在这个例子中,我们将text参数设置为False,并将cat命令的二进制输出写入了一个二进制文件。

子进程信号处理

Subprocess库还允许你在父进程中处理子进程的信号,例如在父进程中捕获子进程的Ctrl C信号。可以使用signal模块结合subprocess来实现这一点:

代码语言:javascript复制
pythonCopy codeimport subprocess
import signal
import time

def signal_handler(sig, frame):
    print(f'Received signal {sig}')

signal.signal(signal.SIGINT, signal_handler)

process = subprocess.Popen(['sleep', '10'])
process.wait()

在这个例子中,我们使用signal.signal()来注册一个信号处理函数,然后通过subprocess.Popen启动了一个睡眠10秒的子进程。当父进程接收到Ctrl C信号时,将调用信号处理函数。

异步子进程管理

Subprocess库还提供了异步执行子进程的能力,适用于异步编程环境。你可以使用asyncio库结合subprocessasyncio模块来实现异步子进程管理:

代码语言:javascript复制
pythonCopy codeimport asyncio
import subprocess

async def run_command():
    process = await asyncio.create_subprocess_exec(
        'ls', '-l',
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
    )

    stdout, stderr = await process.communicate()
    print(f'Stdout: {stdout.decode()}')
    print(f'Stderr: {stderr.decode()}')

asyncio.run(run_command())

在这个例子中,我们使用asyncio.create_subprocess_exec()创建异步子进程,并通过await process.communicate()等待子进程完成。这使得在执行异步子进程的同时,主事件循环可以继续处理其他任务。

子进程间的数据传递

除了使用管道进行进程间通信,Subprocess库还支持使用subprocess.send_signal()subprocess.terminate()等方法向子进程发送信号。以下是一个使用信号通信的例子:

代码语言:javascript复制
pythonCopy codeimport subprocess
import time

process = subprocess.Popen(['python', 'child_process.py'])

# 等待子进程完成
process.wait()

# 向子进程发送SIGTERM信号
process.send_signal(subprocess.signal.SIGTERM)

# 等待一段时间
time.sleep(2)

# 强制终止子进程
process.terminate()

在这个例子中,我们使用subprocess.send_signal()向子进程发送SIGTERM信号,然后使用process.terminate()强制终止子进程。

使用context manager管理进程

Subprocess库还提供了subprocess.Popen对象的上下文管理器接口,可以使用with语句更方便地管理子进程的生命周期:

代码语言:javascript复制
pythonCopy codeimport subprocess

with subprocess.Popen(['echo', 'Hello, Subprocess!'], stdout=subprocess.PIPE, text=True) as process:
    output, _ = process.communicate()
    print(output)

在这个例子中,使用with语句确保在退出代码块时,subprocess.Popen对象被正确地关闭和清理。

自定义子进程启动

如果你需要更细粒度地控制子进程的启动过程,可以使用subprocess.STARTUPINFOsubprocess.CREATE_NO_WINDOW等参数。以下是一个例子:

代码语言:javascript复制
pythonCopy codeimport subprocess
import subprocess

startup_info = subprocess.STARTUPINFO()
startup_info.dwFlags |= subprocess.CREATE_NEW_CONSOLE  # 创建新的控制台窗口

process = subprocess.Popen(['python', 'child_process.py'], startupinfo=startup_info)
process.wait()

在这个例子中,我们使用subprocess.STARTUPINFO()创建了一个STARTUPINFO对象,并通过设置dwFlags属性创建了一个新的控制台窗口。

跨平台兼容性

Subprocess库在不同的操作系统上表现一致,这使得你的代码更具可移植性。无论是在Windows、Linux还是macOS上,Subprocess库都提供了一致的接口。以下是一个简单的跨平台例子:

代码语言:javascript复制
pythonCopy codeimport subprocess
import platform

if platform.system() == 'Windows':
    command = 'dir'
else:
    command = 'ls -l'

result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, text=True)
print(result.stdout)

在这个例子中,通过检查platform.system()确定当前操作系统,然后选择相应的命令。通过使用shell=True参数,确保在Windows上可以执行带有空格的命令。

使用timeout参数处理超时

Subprocess库的timeout参数是在3.3版本中引入的新功能,它为我们提供了一种优雅地处理子进程运行超时的方式。以下是一个超时处理的例子:

代码语言:javascript复制
pythonCopy codeimport subprocess

try:
    result = subprocess.run(['sleep', '5'], timeout=3)
    print(result.returncode)
except subprocess.TimeoutExpired:
    print("Timeout expired")

在这个例子中,subprocess.run()timeout参数设置为3秒,如果子进程的运行时间超过3秒,将引发TimeoutExpired异常。

获取进程PID

Subprocess库允许你获取启动的子进程的进程ID(PID)。以下是一个获取PID的例子:

代码语言:javascript复制
pythonCopy codeimport subprocess

process = subprocess.Popen(['sleep', '10'])
print(f"Child process PID: {process.pid}")

# 等待子进程完成
process.wait()

在这个例子中,使用process.pid获取了启动的子进程的PID。

使用universal_newlines参数处理换行符

在处理不同平台的文本输出时,Subprocess库提供了universal_newlines参数,帮助你处理不同平台的换行符。以下是一个例子:

代码语言:javascript复制
pythonCopy codeimport subprocess

result = subprocess.run(['echo', 'HellornSubprocess'], stdout=subprocess.PIPE, text=True, universal_newlines=True)
print(result.stdout)

在这个例子中,universal_newlines=True确保在处理输出时,Subprocess库将rn转换为n。

使用input参数交互式输入

有时候,你可能需要在子进程中执行需要用户输入的命令。Subprocess库提供了input参数来实现这个目的。以下是一个交互式输入的例子:

代码语言:javascript复制
pythonCopy codeimport subprocess

user_input = "Hello, Subprocess!"
result = subprocess.run(['python', 'interactive_script.py'], input=user_input, text=True, stdout=subprocess.PIPE)
print(result.stdout)

在这个例子中,我们通过input参数将user_input传递给子进程,实现了交互式输入。

使用check_call检查返回码

subprocess.check_call()函数类似于subprocess.run(),但是只返回返回码而不返回其他信息。如果子进程的返回码不为零,它将引发subprocess.CalledProcessError异常。以下是一个例子:

代码语言:javascript复制
pythonCopy codeimport subprocess

subprocess.check_call(['ls', '-l'])

在这个例子中,subprocess.check_call()执行ls -l命令,如果返回码不为零,则引发异常。

使用shell参数执行复杂命令

有时候,你可能需要执行包含管道、重定向和其他Shell功能的复杂命令。可以通过将shell参数设置为True来实现这一点:

代码语言:javascript复制
pythonCopy codeimport subprocess

result = subprocess.run('echo Hello, Subprocess! | grep Sub', shell=True, stdout=subprocess.PIPE, text=True)
print(result.stdout)

请注意,使用shell=True可能会带来一些安全风险,应当谨慎使用。

使用capture_output参数简化输出捕获

在Python 3.7及以上版本中,subprocess.run()引入了capture_output参数,用于简化输出的捕获。以下是一个例子:

代码语言:javascript复制
pythonCopy codeimport subprocess

result = subprocess.run(['ls', '-l'], capture_output=True, text=True)
print(result.stdout)

在这个例子中,capture_output=True等效于stdout=subprocess.PIPE,这样可以更简洁地捕获子进程的输出。

使用subprocess.DEVNULL避免输出

如果你不关心子进程的输出,可以将stdoutstderr参数设置为subprocess.DEVNULL。以下是一个例子:

代码语言:javascript复制
pythonCopy codeimport subprocess

subprocess.run(['echo', 'Hello, Subprocess!'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)

在这个例子中,subprocess.DEVNULL将子进程的标准输出和标准错误输出都重定向到空设备,即忽略输出。

使用stdin参数传递输入

除了使用input参数进行交互式输入外,你还可以通过stdin参数传递输入给子进程。以下是一个例子:

代码语言:javascript复制
pythonCopy codeimport subprocess

input_data = "Hello, Subprocess!"
result = subprocess.run(['python', 'process_input.py'], input=input_data, text=True, stdout=subprocess.PIPE)
print(result.stdout)

在这个例子中,input_data通过stdin参数传递给子进程,实现了输入的传递。

使用subprocess.Popenshell参数

subprocess.Popen类也提供了shell参数,允许你在启动子进程时使用Shell解释器执行命令。以下是一个例子:

代码语言:javascript复制
pythonCopy codeimport subprocess

process = subprocess.Popen('echo Hello, Subprocess!', shell=True, stdout=subprocess.PIPE, text=True)
output, _ = process.communicate()
print(output)

在这个例子中,shell=True允许直接在Shell中执行命令字符串。

通过subprocess.Popen进行交互式输入

subprocess.Popen类允许你通过stdin参数进行交互式输入。以下是一个例子:

代码语言:javascript复制
pythonCopy codeimport subprocess

process = subprocess.Popen(['python', 'interactive_script.py'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, text=True)

user_input = "Hello, Subprocess!"
output, _ = process.communicate(input=user_input)
print(output)

在这个例子中,通过将stdin=subprocess.PIPE传递给subprocess.Popen,实现了与子进程的交互式输入。

使用subprocess.Popenpreexec_fn参数

subprocess.Popenpreexec_fn参数允许你在子进程启动之前执行一个函数。这在需要在子进程中设置一些操作系统级的属性时很有用。以下是一个例子:

代码语言:javascript复制
pythonCopy codeimport subprocess
import os

def pre_exec_function():
    os.setpgrp()  # 将子进程设置为新的进程组

process = subprocess.Popen(['sleep', '5'], preexec_fn=pre_exec_function)

# 等待子进程完成
process.wait()

在这个例子中,pre_exec_function函数在子进程启动之前被调用,将子进程设置为新的进程组。

使用subprocess.Popenenv参数设置环境变量

subprocess.Popenenv参数允许你设置子进程的环境变量。以下是一个例子:

代码语言:javascript复制
pythonCopy codeimport subprocess

custom_env = {'CUSTOM_VARIABLE': 'custom_value'}
process = subprocess.Popen(['python', 'print_env.py'], env=custom_env, stdout=subprocess.PIPE, text=True)

output, _ = process.communicate()
print(output)

在这个例子中,custom_env字典中的环境变量被传递给子进程。

使用subprocess.Popencwd参数设置工作目录

subprocess.Popencwd参数允许你设置子进程的工作目录。这在需要在特定目录下执行命令时非常有用。以下是一个例子:

代码语言:javascript复制
pythonCopy codeimport subprocess

process = subprocess.Popen(['ls', '-l'], cwd='/path/to/directory', stdout=subprocess.PIPE, text=True)

output, _ = process.communicate()
print(output)

在这个例子中,cwd参数被设置为'/path/to/directory',确保ls -l命令在指定目录中执行。

使用subprocess.Popen进行后台执行

有时候,你可能希望将子进程放入后台执行,而不阻塞父进程。可以使用subprocess.Popenstart_new_session参数实现这一点。以下是一个例子:

代码语言:javascript复制
pythonCopy codeimport subprocess

process = subprocess.Popen(['sleep', '10'], start_new_session=True)

# 继续执行其他任务,而不等待子进程完成

在这个例子中,start_new_session=True将子进程放入新的进程组,使其在后台执行。

使用subprocess.Popenstdin参数进行输入流重定向

subprocess.Popenstdin参数允许你从文件或其他可迭代对象中重定向输入流。以下是一个例子:

代码语言:javascript复制
pythonCopy codeimport subprocess

with open('input.txt', 'r') as input_file:
    process = subprocess.Popen(['python', 'process_input.py'], stdin=input_file, stdout=subprocess.PIPE, text=True)

output, _ = process.communicate()
print(output)

在这个例子中,stdin参数被设置为一个打开的文件对象,从文件中读取输入并传递给子进程。

使用subprocess.Popenstdoutstderr参数进行输出流重定向

subprocess.Popenstdoutstderr参数允许你将子进程的标准输出和标准错误输出重定向到文件或其他地方。以下是一个例子:

代码语言:javascript复制
pythonCopy codeimport subprocess

with open('output.txt', 'w') as output_file:
    process = subprocess.Popen(['ls', '-l'], stdout=output_file, stderr=subprocess.PIPE, text=True)

error_output, _ = process.communicate()
print(error_output)

在这个例子中,stdout参数被设置为一个打开的文件对象,将ls -l命令的标准输出写入文件,而stderr参数被设置为subprocess.PIPE,以便捕获标准错误输出。

使用subprocess.Popenexecutable参数指定可执行文件

subprocess.Popenexecutable参数允许你指定要执行的可执行文件。这在需要灵活指定可执行文件路径时很有用。以下是一个例子:

代码语言:javascript复制
pythonCopy codeimport subprocess

process = subprocess.Popen(['script.sh'], executable='/bin/bash', stdout=subprocess.PIPE, text=True)

output, _ = process.communicate()
print(output)

在这个例子中,executable参数被设置为'/bin/bash',指定了要执行的Shell解释器。

使用subprocess.Popenshell参数执行Shell命令

subprocess.Popenshell参数允许你在启动子进程时执行Shell命令。这在需要执行包含Shell语法的命令时非常有用。以下是一个例子:

代码语言:javascript复制
pythonCopy codeimport subprocess

process = subprocess.Popen('echo Hello, Subprocess!', shell=True, stdout=subprocess.PIPE, text=True)

output, _ = process.communicate()
print(output)

在这个例子中,shell=True允许直接在Shell中执行命令字符串。

使用subprocess.Popenencoding参数指定字符编码

subprocess.Popenencoding参数允许你指定子进程的标准输入、标准输出和标准错误输出的字符编码。以下是一个例子:

代码语言:javascript复制
pythonCopy codeimport subprocess

process = subprocess.Popen(['echo', '你好'], stdout=subprocess.PIPE, text=True, encoding='utf-8')

output, _ = process.communicate()
print(output)

在这个例子中,encoding参数被设置为'utf-8',确保处理子进程输出时使用正确的字符编码。

使用subprocess.Popentimeout参数设置超时时间

subprocess.Popentimeout参数允许你设置子进程的最长运行时间,以避免因子进程无法正常退出而导致父进程一直等待。以下是一个例子:

代码语言:javascript复制
pythonCopy codeimport subprocess

try:
    process = subprocess.Popen(['sleep', '5'], stdout=subprocess.PIPE, text=True, timeout=3)
    output, _ = process.communicate()
    print(output)
except subprocess.TimeoutExpired:
    print("Timeout expired")

在这个例子中,timeout参数被设置为3秒,如果子进程的运行时间超过3秒,将引发TimeoutExpired异常。

使用subprocess.Popenpreexec_fn参数设置子进程的启动前操作

subprocess.Popenpreexec_fn参数允许你在子进程启动之前执行一个函数。这在需要在子进程中执行一些特定的操作时很有用。以下是一个例子:

代码语言:javascript复制
pythonCopy codeimport subprocess
import os

def pre_exec_function():
    os.setpgrp()  # 将子进程设置为新的进程组

process = subprocess.Popen(['sleep', '10'], preexec_fn=pre_exec_function)

# 等待子进程完成
process.wait()

在这个例子中,pre_exec_function函数在子进程启动之前被调用,将子进程设置为新的进程组。

使用subprocess.Popenstart_new_session参数进行后台执行

有时候,你可能希望将子进程放入后台执行,而不阻塞父进程。可以使用subprocess.Popenstart_new_session参数实现这一点。以下是一个例子:

代码语言:javascript复制
pythonCopy codeimport subprocess

process = subprocess.Popen(['sleep', '10'], start_new_session=True)

# 继续执行其他任务,而不等待子进程完成

在这个例子中,start_new_session=True将子进程放入新的进程组,使其在后台执行。

使用subprocess.Popenclose_fds参数关闭文件描述符

subprocess.Popenclose_fds参数允许你在子进程中关闭不必要的文件描述符。以下是一个例子:

代码语言:javascript复制
pythonCopy codeimport subprocess

process = subprocess.Popen(['ls', '-l'], close_fds=True, stdout=subprocess.PIPE, text=True)

output, _ = process.communicate()
print(output)

在这个例子中,close_fds=True确保子进程中的不必要文件描述符被关闭。

使用subprocess.Popenrestore_signals参数还原信号处理

在Unix系统上,subprocess.Popenrestore_signals参数允许你在子进程启动时还原信号处理为默认值。以下是一个例子:

代码语言:javascript复制
pythonCopy codeimport subprocess

process = subprocess.Popen(['sleep', '10'], restore_signals=True)

# 等待子进程完成
process.wait()

在这个例子中,restore_signals=True将在子进程启动时还原信号处理为默认值。

使用subprocess.Popenpass_fds参数传递文件描述符

subprocess.Popenpass_fds参数允许你将指定的文件描述符传递给子进程。以下是一个例子:

代码语言:javascript复制
pythonCopy codeimport subprocess

# 创建一个文件并获取其文件描述符
with open('example.txt', 'w') as file:
    file_descriptor = file.fileno()

process = subprocess.Popen(['cat'], pass_fds=[file_descriptor])

# 等待子进程完成
process.wait()

在这个例子中,pass_fds参数传递了文件描述符给子进程,使子进程能够读取该文件。

使用subprocess.Popentimeout参数设置超时时间

subprocess.Popentimeout参数允许你设置子进程的最长运行时间,以避免因子进程无法正常退出而导致父进程一直等待。以下是一个例子:

代码语言:javascript复制
pythonCopy codeimport subprocess

try:
    process = subprocess.Popen(['sleep', '5'], stdout=subprocess.PIPE, text=True, timeout=3)
    output, _ = process.communicate()
    print(output)
except subprocess.TimeoutExpired:
    print("Timeout expired")

在这个例子中,timeout参数被设置为3秒,如果子进程的运行时间超过3秒,将引发TimeoutExpired异常。

使用subprocess.Popenuniversal_newlines参数处理换行符

subprocess.Popenuniversal_newlines参数在处理不同平台的文本输出时很有用,它将换行符转换为n。以下是一个例子:

代码语言:javascript复制
pythonCopy codeimport subprocess

result = subprocess.run(['echo', 'HellornSubprocess'], stdout=subprocess.PIPE, text=True, universal_newlines=True)
print(result.stdout)

在这个例子中,universal_newlines=True确保在处理输出时将rn转换为n

使用subprocess模块的check_output函数获取子进程输出

subprocess模块的check_output函数用于运行命令并获取其标准输出。以下是一个例子:

代码语言:javascript复制
pythonCopy codeimport subprocess

output = subprocess.check_output(['echo', 'Hello, Subprocess!'], text=True)
print(output)

在这个例子中,check_output函数运行echo命令并返回其输出。

使用subprocess模块的call函数运行命令

subprocess模块的call函数用于运行命令,它返回命令的退出状态码。以下是一个例子:

代码语言:javascript复制
pythonCopy codeimport subprocess

status_code = subprocess.call(['ls', '-l'], text=True)
print(f"Command exited with status code: {status_code}")

在这个例子中,call函数运行ls -l命令并打印其退出状态码。

使用subprocess模块的run函数运行命令

subprocess模块的run函数是一个更强大的函数,可以更灵活地处理命令执行。以下是一个例子:

代码语言:javascript复制
pythonCopy codeimport subprocess

result = subprocess.run(['echo', 'Hello, Subprocess!'], stdout=subprocess.PIPE, text=True)
print(result.stdout)

在这个例子中,run函数运行echo命令,并通过stdout=subprocess.PIPE参数捕获其标准输出。

使用subprocess模块的TimeoutExpired处理超时

subprocess.run函数可以使用timeout参数设置超时时间,如果命令执行时间超过指定的时间,将引发TimeoutExpired异常。以下是一个例子:

代码语言:javascript复制
pythonCopy codeimport subprocess

try:
    result = subprocess.run(['sleep', '5'], timeout=3, text=True)
    print(result.stdout)
except subprocess.TimeoutExpired:
    print("Command timed out")

在这个例子中,timeout参数被设置为3秒,如果sleep 5命令执行时间超过3秒,将引发TimeoutExpired异常。

使用subprocess模块的stderr参数获取标准错误输出

subprocess.run函数的stderr参数允许你获取命令的标准错误输出。以下是一个例子:

代码语言:javascript复制
pythonCopy codeimport subprocess

result = subprocess.run(['ls', 'nonexistent_file'], stderr=subprocess.PIPE, text=True)

if result.returncode != 0:
    print(f"Error: {result.stderr}")

在这个例子中,stderr=subprocess.PIPE参数允许获取ls nonexistent_file命令的标准错误输出。

结论

subprocess模块提供了多个函数和常量,用于更方便地执行子进程。通过灵活使用这些函数和常量,你可以满足不同的需求,从而更有效地管理和控制子进程。希望这个教程能够帮助大家更全面地了解subprocess模块的用法。

0 人点赞