【发布时间】:2016-07-13 14:09:10
【问题描述】:
是否有从subprocess.Popen 和 zmq 套接字轮询 stdout/stderr 的最佳实践方法?
就我而言,我的主程序生成了一个 Popen 子进程。子进程通过 zmq 发布消息,然后我想在我的主程序中订阅这些消息。
使用zmq.Poller 等待多个 zmq 套接字并不复杂,但是当我想将其与子进程本身的输出交错时,我不确定如何以最好的方式做到这一点,而不会冒等待或产生不必要的循环的风险。
最后,我想这样使用它:
process = Popen([prog, '--publish-to', 'tcp://127.0.0.1:89890'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE, ...)
for (origin, data) in interleave(process, 'tcp://127.0.0.1:89890'):
if origin == 'STDOUT': pass
if origin == 'STDERR': pass
if origin == 'ZMQ': pass
prog --publish-to tcp://127.0.0.1:89890 然后将打开一个zmq.PUB 套接字并发布数据,而 interleave 函数将订阅它并轮询 stdout 和 stderr,yielding 任何数据首先到达它。
我知道如何使用多个守护线程和队列定义interleave,但我不知道这种方法是否可能对延迟读取有一些警告(即,可能直到程序结束才处理标准输出? ) 或其他我还没有考虑过的事情(对于这样的任务似乎也有相当多的开销)。
我会感谢所有想法或见解。
我的目标是至少使用 Python 3.3/3.4,但如果使用新的 async/await 工具更容易做到这一点,我也可以使用 Python 3.5 编写代码。
【问题讨论】:
-
您可以使用
process.stdout.fileno()获取整数文件描述符。如果你能得到 zmq 套接字的文件描述符,你可以做一个select.select((fd1, d2, fd3), (), (), None)调用来等待第一个。如果无法获取 zmq 套接字的文件描述符,则可以创建 2 或 3 个线程,它们都从一个源读取(并被阻塞),将读取的数据放入Queue。 -
嗯,
select也可以在 Windows 上工作吗?不幸的是,这将是一个障碍。