[英]How to stream messages in a pipe from one process to another?
I have 2 python (2.7) processes. 我有2个python(2.7)进程。
The parent process needs to send rows of text to a child process, and the child process should process them as they come in (not wait for the parent process to finish). 父流程需要将文本行发送给子流程,子流程应在输入时处理它们(而不是等待父流程完成)。
I have this code which doesn't work: 我有此代码不起作用:
# Sender
import subprocess
process = subprocess.Popen(['python', 'child.py'], bufsize=1, stdin=subprocess.PIPE)
try:
while True:
process.stdin.write(msg + '\n') # 'msg' is a changing string
# process.stdin.flush() <-- commented out since it doesn't help
except KeyboardInterrupt:
process.stdin.close()
process.wait()
And the child process: 和子进程:
# Receiver
import sys
for line in sys.stdin:
print line.strip()
The problem is that the child process waits until the parent process exits before it prints out the messages. 问题是子进程会等到父进程退出后才打印出消息。
What I'm trying to achieve is a child process that processes the messages as soon as they are written to the pipe. 我想要实现的是一个子进程,该子进程会在将消息写入管道后立即对其进行处理。
Try adding a process.stdin.flush()
after your process.stdin.write()
. 尝试在process.stdin.flush()
之后添加process.stdin.write()
。 That way you actually send the string to the other process. 这样,您实际上会将字符串发送给其他进程。 What you're suffering from here is your kernel caching everything you write. 您在这里遭受的是您的内核将您编写的所有内容都缓存。 It does this to be more efficient when actually sending the data to the other process. 实际将数据发送到其他进程时,这样做可以提高效率。 flush force the kernel to send your data regardless of how full the kernel's buffer is. 刷新将强制内核发送您的数据,而不管内核的缓冲区有多满。
I tried your code as such: 我尝试了这样的代码:
# Sender
import subprocess
process = subprocess.Popen(['python', 'child.py'], bufsize=1, stdin=subprocess.PIPE)
msg = "This is my message"
try:
while True:
process.stdin.write(msg + '\n') # 'msg' is a changing string
process.stdin.flush() # This code works well for me regardless of the presence of this line
except KeyboardInterrupt:
process.stdin.close()
process.wait()
# Receiver
import sys
for line in sys.stdin:
print line.strip()
With "works well" here i mean that i get "This is my message" printed as fast as the computer can perform. 这里的“效果很好”是指我以计算机可以执行的速度打印“这是我的消息”。 I'm trying this in Python 2.7.12 for the record. 我正尝试在Python 2.7.12中进行记录。
The story of how buffering works for sys.stdin
and sys.stdout
has made me cry more than once. 关于sys.stdin
和sys.stdout
缓冲工作原理的故事使我不止一次哭泣。 A similar problem is discussed in Setting smaller buffer size for sys.stdin? 为sys.stdin设置较小的缓冲区大小中讨论了类似的问题。 . 。
As to your specific problem, I suggest you change your child to use sys.stdin.readline()
instead of iterating over sys.stdin
. 关于您的特定问题,建议您更改孩子以使用sys.stdin.readline()
而不是遍历sys.stdin
。 The former somewhat "buffers less" :) 前者有些“缓冲较少” :)
while True:
line = sys.stdin.readline()
if not line: break
print (line.strip())
In the parent, you'll likely either need to set bufsize=0
in your call to Popen
(making your pipe completely unbuffered), or you'll need the process.stdin.flush()
line, as Patrik suggests. 在父级中,您可能需要在对Popen
的调用中设置bufsize=0
(使管道完全无缓冲),或者需要如Patrik建议的那样使用process.stdin.flush()
行。 I'd opt for the latter. 我选择后者。
Tested on Python 2.7.14 on Windows 10 64bit. 已在Windows 10 64bit的Python 2.7.14上测试。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.