如何在 Python 子进程中立即读取标准输出
How to read stdout immediately in Python subprocess
我正在尝试创建两个 python 进程。
main.py
child = Popen(['python.exe', 'test.py'], stdin=PIPE, stdout=PIPE, stderr=STDOUT)
stdout, stderr = child.communicate(input='hello world'.encode())
result = stdout.decode()
print(result)
test.py
value = sys.stdin.read()
sys.stdout.write(value)
time.sleep(10)
(time.sleep只是一个耗时任务的例子。)
在这种情况下,main.py
等待 10 秒 test.py
结束后再打印。
有没有办法在 sys.stdout.write
之后立即从 test.py
打印标准输出?
一个给你的例子,你多次读写 child(正如你在问题下的评论中所说)。
子进程 (test.py
) 将:
- 读一行
- 将每一个都转换为大写,然后写回,
- 睡2秒
- 重复直到没有更多输入,然后写最后一行
主进程(main.py
)将:
- 三次:
- 向子进程写入一行输入
- 阅读答案并说出得到答案需要多长时间
- 睡 5 秒
- 最后,使用
communicate
读取任何最终输出,并报告此
下面是代码的输出:
writing to child: hello world 0
child replied with: HELLO WORLD 0
got answer back within 0.00022 seconds
writing to child: hello world 1
child replied with: HELLO WORLD 1
got answer back within 0.00012 seconds
writing to child: hello world 2
child replied with: HELLO WORLD 2
got answer back within 0.00021 seconds
final output from child: finishing
这是代码:
test.py
import sys
import time
while True:
value = sys.stdin.readline()
if not value:
break
sys.stdout.write(value.upper())
sys.stdout.flush()
time.sleep(2)
sys.stdout.write("finishing\n")
main.py
from subprocess import Popen, PIPE, STDOUT
import time
child = Popen(['python.exe', 'test.py'], stdin=PIPE, stdout=PIPE, stderr=STDOUT)
time.sleep(1)
for i in range(3):
data_in = f"hello world {i}"
print(f"writing to child: {data_in}")
time0 = time.time()
child.stdin.write(f"{data_in}\n".encode())
child.stdin.flush()
data_out = child.stdout.readline()
time1 = time.time()
result = data_out.decode().strip()
elapsed_time = time1 - time0
print(f"child replied with: {result}")
print(f"got answer back within {elapsed_time:.5f} seconds\n")
time.sleep(5)
output, error = child.communicate()
print(f"final output from child: {output.decode()}")
(在 Linux 上使用 python
而不是 python.exe
进行了测试 - 希望它在 Windows 上同样有效,尽管我无法对此进行测试.)
如您所见,无需等待 sleep
完成即可收到答案。
(显然如果parent中的休眠时间减少到2秒以下,那么child在发送数据时就不会准备好接收数据了,那么就会有等待得到答复。)
使用这种 two-way 通信,很容易陷入死锁状态(每个进程都在等待另一个进程做某事)。为避免这种情况,每个进程每次只写一行,确保它以换行符结尾,并立即刷新输出缓冲区——读取进程使用 readline()
只读取一行(读取到换行符)。那么希望两人能步调一致,避免僵局。
我正在尝试创建两个 python 进程。
main.py
child = Popen(['python.exe', 'test.py'], stdin=PIPE, stdout=PIPE, stderr=STDOUT)
stdout, stderr = child.communicate(input='hello world'.encode())
result = stdout.decode()
print(result)
test.py
value = sys.stdin.read()
sys.stdout.write(value)
time.sleep(10)
(time.sleep只是一个耗时任务的例子。)
在这种情况下,main.py
等待 10 秒 test.py
结束后再打印。
有没有办法在 sys.stdout.write
之后立即从 test.py
打印标准输出?
一个给你的例子,你多次读写 child(正如你在问题下的评论中所说)。
子进程 (test.py
) 将:
- 读一行
- 将每一个都转换为大写,然后写回,
- 睡2秒
- 重复直到没有更多输入,然后写最后一行
主进程(main.py
)将:
- 三次:
- 向子进程写入一行输入
- 阅读答案并说出得到答案需要多长时间
- 睡 5 秒
- 最后,使用
communicate
读取任何最终输出,并报告此
下面是代码的输出:
writing to child: hello world 0
child replied with: HELLO WORLD 0
got answer back within 0.00022 seconds
writing to child: hello world 1
child replied with: HELLO WORLD 1
got answer back within 0.00012 seconds
writing to child: hello world 2
child replied with: HELLO WORLD 2
got answer back within 0.00021 seconds
final output from child: finishing
这是代码:
test.py
import sys
import time
while True:
value = sys.stdin.readline()
if not value:
break
sys.stdout.write(value.upper())
sys.stdout.flush()
time.sleep(2)
sys.stdout.write("finishing\n")
main.py
from subprocess import Popen, PIPE, STDOUT
import time
child = Popen(['python.exe', 'test.py'], stdin=PIPE, stdout=PIPE, stderr=STDOUT)
time.sleep(1)
for i in range(3):
data_in = f"hello world {i}"
print(f"writing to child: {data_in}")
time0 = time.time()
child.stdin.write(f"{data_in}\n".encode())
child.stdin.flush()
data_out = child.stdout.readline()
time1 = time.time()
result = data_out.decode().strip()
elapsed_time = time1 - time0
print(f"child replied with: {result}")
print(f"got answer back within {elapsed_time:.5f} seconds\n")
time.sleep(5)
output, error = child.communicate()
print(f"final output from child: {output.decode()}")
(在 Linux 上使用 python
而不是 python.exe
进行了测试 - 希望它在 Windows 上同样有效,尽管我无法对此进行测试.)
如您所见,无需等待 sleep
完成即可收到答案。
(显然如果parent中的休眠时间减少到2秒以下,那么child在发送数据时就不会准备好接收数据了,那么就会有等待得到答复。)
使用这种 two-way 通信,很容易陷入死锁状态(每个进程都在等待另一个进程做某事)。为避免这种情况,每个进程每次只写一行,确保它以换行符结尾,并立即刷新输出缓冲区——读取进程使用 readline()
只读取一行(读取到换行符)。那么希望两人能步调一致,避免僵局。