多处理.Process的日志输出

ast*_*rog 65 python concurrency logging multiprocessing

有没有办法在python中使用multiprocessing.Process类时记录给定进程的stdout输出?

Mar*_*off 53

最简单的方法可能是覆盖sys.stdout.稍微修改多处理手册中的示例:

from multiprocessing import Process
import os
import sys

def info(title):
    print title
    print 'module name:', __name__
    print 'parent process:', os.getppid()
    print 'process id:', os.getpid()

def f(name):
    sys.stdout = open(str(os.getpid()) + ".out", "w")
    info('function f')
    print 'hello', name

if __name__ == '__main__':
    p = Process(target=f, args=('bob',))
    p.start()
    q = Process(target=f, args=('fred',))
    q.start()
    p.join()
    q.join()
Run Code Online (Sandbox Code Playgroud)

运行它:

$ ls
m.py
$ python m.py
$ ls
27493.out  27494.out  m.py
$ cat 27493.out 
function f
module name: __main__
parent process: 27492
process id: 27493
hello bob
$ cat 27494.out 
function f
module name: __main__
parent process: 27492
process id: 27494
hello fred


Hey*_*his 16

我只会向@Mark Rushakoff回答两件事.调试时,我发现将调用buffering参数更改open()为0 非常有用.

sys.stdout = open(str(os.getpid()) + ".out", "a", buffering=0)
Run Code Online (Sandbox Code Playgroud)

否则,疯狂,因为在tail -f输出文件时,结果可能是间歇性的.buffering=0为了tail -f伟大.

为了完整起见,请自己帮忙并重定向sys.stderr.

sys.stderr = open(str(os.getpid()) + "_error.out", "a", buffering=0)
Run Code Online (Sandbox Code Playgroud)

另外,为方便起见,如果您愿意,可以将其转储到单独的流程类中,

class MyProc(Process):
    def run(self):
        # Define the logging in run(), MyProc's entry function when it is .start()-ed 
        #     p = MyProc()
        #     p.start()
        self.initialize_logging()

        print 'Now output is captured.'

        # Now do stuff...

    def initialize_logging(self):
        sys.stdout = open(str(os.getpid()) + ".out", "a", buffering=0)
        sys.stderr = open(str(os.getpid()) + "_error.out", "a", buffering=0)

        print 'stdout initialized'
Run Code Online (Sandbox Code Playgroud)

这是一个相应的要点

  • 我在python 3.6中尝试此操作时遇到ValueError,因为buffering = 0仅适用于二进制模式。但是,您可以通过从sys.stdout / stderr的猴子补丁中删除buffering = 0并在输出语句中添加flush = True来解决此问题。即print(“ Stdout初始化”,flush = True)。它像一种魅力。 (4认同)

Ale*_*lli 11

您可以设置sys.stdout = Logger()其中Logger的一类,其write方法(马上,或累积,直到\n检测到)调用logging.info(或要登录任何其他方式).这个实例的一个例子.

我不确定你所说的"给定"过程是什么意思(谁给出了它,它与其他所有人的区别......?),但是如果你的意思是你知道你想要在那个时候以那种方式挑出什么过程实例化它,然后你可以将它的target函数(以及那个) - 或者run你在Process子类中重写的方法- 包装到执行这个sys.stdout"重定向"的包装器中 - 并保留其他进程.

也许如果你对规格有所了解,我可以更详细地帮助......?