python - 如何从使用多处理运行脚本的 python2 子进程获取输出?

标签 python python-2.7 subprocess multiprocessing

这是我的演示代码。它包含两个脚本。

第一个是main.py,它将使用子进程模块调用print_line.py

第二个是print_line.py,它向标准输出打印一些内容。

main.py

import subprocess

p = subprocess.Popen('python2 print_line.py',
                     stdout=subprocess.PIPE,
                     stderr=subprocess.PIPE,
                     close_fds=True,
                     shell=True,
                     universal_newlines=True)

while True:
    line = p.stdout.readline()
    if line:
        print(line)
    else:
        break

打印行.py

from multiprocessing import Process, JoinableQueue, current_process


if __name__ == '__main__':
    task_q = JoinableQueue()

    def do_task():
        while True:
            task = task_q.get()
            pid = current_process().pid
            print 'pid: {}, task: {}'.format(pid, task)
            task_q.task_done()

    for _ in range(10):
        p = Process(target=do_task)
        p.daemon = True
        p.start()

    for i in range(100):
        task_q.put(i)

    task_q.join()

之前,print_line.py是用线程和队列模块编写的,一切都很好。但现在,在更改为多处理模块后,main.py无法从print_line获取任何输出。我尝试使用 Popen.communicate() 获取输出或在 Popen() 中设置 preexec_fn=os.setsid 。它们都不起作用。

所以,这是我的问题:

  1. 为什么子进程无法通过多重处理获得输出?为什么线程可以?

  2. 如果我注释掉 stdout=subprocess.PIPEstderr=subprocess.PIPE,输出将打印在我的控制台中。为什么?这是怎么发生的?

  3. 是否有机会从 print_line.py 获取输出?

最佳答案

好奇。

理论上,这应该按原样工作,但事实并非如此。原因在于缓冲 IO 的深水区。看来,如果不刷新,子进程的子进程的输出可能会丢失。

您有两种解决方法:

一种是在 print_line.py 中使用 flush():

def do_task():
    while True:
        task = task_q.get()
        pid = current_process().pid
        print 'pid: {}, task: {}'.format(pid, task)
        sys.stdout.flush()
        task_q.task_done()

这将解决这个问题,因为一旦你向标准输出写入内容,你就会刷新它。

另一种选择是在 main.py 中使用 Python 的 -u 标志:

p = subprocess.Popen('python2 -u print_line.py',
                     stdout=subprocess.PIPE,
                     stderr=subprocess.PIPE,
                     close_fds=True,
                     shell=True,
                     universal_newlines=True)

-u 将强制 stdin 和 stdout 在 print_line.py 中完全无缓冲,并且 print_line.py 的子级将继承它行为。

这些是解决该问题的方法。如果您对发生这种情况的理论感兴趣,它肯定与子进程终止时未刷新的标准输出丢失有关,但我不是这方面的专家。

关于python - 如何从使用多处理运行脚本的 python2 子进程获取输出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47626299/

相关文章:

python - 解决 I/O 限制问题的最佳方法?

python 的 len(list(filter(lambda x : criteria, iterable))) 快捷方式

python - matplotlib 的表格图例布局

python - 从字典列表中删除重复项

python-2.7 - 如何用keras函数式api查看神经网络的总结

python - 在 shell 中将文件从 iso-8859-1 转换为 utf-8 iconv 与使用子进程从 python 调用它的结果不同

python - 如何中断事件信息以进行记录

c++ - 如何在caffe中提取图层的blob信息?

python - 设置自定义轴值 pyplot

python - Gunicorn + 子进程引发异常 [Errno 10]