Python与子进程通信
我有一个子进程,它一直在产生数据,但大部分数据我并不感兴趣。不过偶尔在随机的时间,我需要抓取一小部分输出。关键是我需要在明确的边界上读取这些数据。比如,假设这个进程每秒产生100字节的数据,而有用的信息是以100字节为一块的。假如它运行了4秒后,我想查看100字节的输出,那么我需要的是第400到499字节的数据。但如果我在4.1秒的时候请求数据,我就不想得到第410到509字节的数据,而是要等到第500到599字节的数据。否则,这个进程应该继续把输出流畅地发送到/dev/null
,而我不想阻塞输出流。我的朋友Fred可能也会在4.6秒的时候请求100字节的数据,所以我还需要把这些数据分发出去,让多个消费者可以读取。
有没有现成的设计模式可以解决这个问题?我该如何用Python的子进程来实现,并确保与子进程的通信是不阻塞的?
3 个回答
import subprocess
subProc= subprocess.Popen(['tail','/dev/random'],stdout=subprocess.PIPE)
subProc.stdout[400:499] ?
或者
subProc.stdout.seek(400).read(100)
如果这些都不行,试试:
var = subProc.stdout
var[400:499]
另外,如果我没记错的话,在Python3.X中,要想从你的子进程中得到正确的输出,你需要不时地调用flush():
sys.stdout.flush()
出于某种奇怪的原因,我无法访问我的任何Unix环境,所以我实际上无法测试这段代码,但理论上这应该能满足你的要求。
我刚接触Python,但我发现proc.communicate或者proc.stdout.readline/readlines会等到进程完成后才继续执行。
根据我的了解,你可以实现一个循环日志记录,把输出重定向到一个文件里。然后使用subprocess模块,你可以在一个循环中运行tailf -n XX logfile,直到程序结束,并在用户需要的时候打印输出。
你可能想要不断地从标准输出(stdout)读取数据,每次读取100字节。然后,你会有一系列的“消费者”,这些消费者可以简单地实现为接收字符串或字节串的函数(这取决于你使用的是Python 2.x还是3.x)。每次读取的数据块都会发送给每个消费者,然后就被丢弃。
大概是这样的:
def f_a(s): pass
def f_b(s): pass
consumers = [f_a, f_b]
while True:
chunk = process.stdout.read(100)
if chunk == '': break # or something like that
for c in consumers: c(chunk)
如果你在一个线程中运行这个,你可以根据需要随意修改消费者。
不过,你要注意消费者不要阻塞——否则你的循环也会被阻塞。如果阻塞时间不长,这没什么问题,因为操作系统会在你的子进程和你之间提供一个相当大的缓冲区。但这个缓冲区不是无限的。所以可能需要在每个消费者或者在循环中添加一些缓冲机制。