Subprocess.Popen
是 Python 中用于创建新进程并与之通信的类。STDOUT
是这个类的一个属性,通常用于捕获子进程的标准输出。然而,STDOUT
本身并不支持直接分配多个属性,因为它本质上是一个文件描述符或类似文件的对象。
如果你想要处理多个输出流,你可以考虑以下几种方法:
PIPE
并分别捕获输出你可以为 stdout
和 stderr
分别设置 PIPE
,然后分别读取它们的输出。
import subprocess
# 启动子进程,同时捕获 stdout 和 stderr
process = subprocess.Popen(['your_command', 'arg1', 'arg2'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# 读取 stdout 和 stderr 的输出
stdout_output, stderr_output = process.communicate()
# 将输出从字节转换为字符串(如果需要)
stdout_str = stdout_output.decode('utf-8')
stderr_str = stderr_output.decode('utf-8')
print('STDOUT:', stdout_str)
print('STDERR:', stderr_str)
如果你担心 communicate()
方法会阻塞,你可以使用线程来同时读取 stdout
和 stderr
。
import subprocess
import threading
def read_output(stream, output_list):
for line in iter(stream.readline, b''):
output_list.append(line.decode('utf-8'))
stream.close()
process = subprocess.Popen(['your_command', 'arg1', 'arg2'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout_list = []
stderr_list = []
# 创建并启动线程
stdout_thread = threading.Thread(target=read_output, args=(process.stdout, stdout_list))
stderr_thread = threading.Thread(target=read_output, args=(process.stderr, stderr_list))
stdout_thread.start()
stderr_thread.start()
# 等待线程完成
stdout_thread.join()
stderr_thread.join()
# 获取输出
stdout_output = ''.join(stdout_list)
stderr_output = ''.join(stderr_list)
print('STDOUT:', stdout_output)
print('STDERR:', stderr_output)
select
模块非阻塞读取你还可以使用 select
模块来非阻塞地读取多个输出流。
import subprocess
import select
process = subprocess.Popen(['your_command', 'arg1', 'arg2'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
outputs = {'stdout': [], 'stderr': []}
while True:
reads, _, _ = select.select([process.stdout, process.stderr], [], [])
for fd in reads:
if fd == process.stdout:
output = process.stdout.readline().decode('utf-8')
if output:
outputs['stdout'].append(output)
elif fd == process.stderr:
output = process.stderr.readline().decode('utf-8')
if output:
outputs['stderr'].append(output)
if process.poll() is not None:
break
stdout_output = ''.join(outputs['stdout'])
stderr_output = ''.join(outputs['stderr'])
print('STDOUT:', stdout_output)
print('STDERR:', stderr_output)
这些方法在需要捕获和处理子进程的多个输出流时非常有用,例如:
communicate()
方法时,如果子进程产生大量输出,可能会导致死锁。使用线程或 select
可以避免这个问题。通过以上方法,你可以有效地处理 Subprocess.Popen
的多个输出流,并根据具体需求选择合适的方法。
云+社区沙龙online第6期[开源之道]
云+社区沙龙online
云+社区沙龙online [云原生技术实践]
云+社区技术沙龙[第19期]
企业创新在线学堂
云+社区技术沙龙[第14期]
企业创新在线学堂
领取专属 10元无门槛券
手把手带您无忧上云