捕获输出并在后台运行 threading
如本答案所述,如果您使用捕获输出,stdout=
然后尝试进行read()
,则该过程将阻塞。
但是,在某些情况下您需要这样做。例如,我想启动两个进程,它们通过它们之间的端口进行通信,并将它们的stdout保存到日志文件和stdout中。
该threading
模块使我们能够做到这一点。
首先,看看如何在此问题中单独完成输出重定向:Python Popen:同时写入stdout和日志文件
然后:
main.py
#!/usr/bin/env python3
import os
import subprocess
import sys
import threading
def output_reader(proc, file):
while True:
byte = proc.stdout.read(1)
if byte:
sys.stdout.buffer.write(byte)
sys.stdout.flush()
file.buffer.write(byte)
else:
break
with subprocess.Popen(['./sleep.py', '0'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) as proc1, \
subprocess.Popen(['./sleep.py', '10'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) as proc2, \
open('log1.log', 'w') as file1, \
open('log2.log', 'w') as file2:
t1 = threading.Thread(target=output_reader, args=(proc1, file1))
t2 = threading.Thread(target=output_reader, args=(proc2, file2))
t1.start()
t2.start()
t1.join()
t2.join()
sleep.py
#!/usr/bin/env python3
import sys
import time
for i in range(4):
print(i + int(sys.argv[1]))
sys.stdout.flush()
time.sleep(0.5)
运行后:
./main.py
标准输出每0.5秒更新一次,每两行包含一次:
0
10
1
11
2
12
3
13
每个日志文件都包含给定进程的相应日志。
灵感来源:https://eli.thegreenplace.net/2017/interacting-with-a-long-running-child-process-in-python/
已在Ubuntu 18.04,Python 3.6.7上测试。