multiprocessing.Process的日志输出

82 投票
6 回答
69569 浏览
提问于 2025-04-15 14:43

有没有办法在使用python的multiprocessing.Process类时,记录一个Process的标准输出(stdout)呢?

6 个回答

14

你可以把 sys.stdout = Logger() 这行代码放进去,其中 Logger 是一个类,它的 write 方法会在接收到数据后(要么立刻,要么等到看到 \n 这个换行符)调用 logging.info(或者你想用的任何记录方式)。这里有个实际例子。

我不太明白你说的“某个特定的”进程是什么意思(是谁给它的,跟其他进程有什么不同……?),不过如果你是说在创建这个进程的时候就知道你想单独处理哪个进程,那你可以把它的 target 函数(就这一部分)或者你在 Process 子类中重写的 run 方法,放到一个包装器里,这样就可以实现这个 sys.stdout 的“重定向”,而不影响其他进程。

也许如果你能把具体要求说得更清楚一点,我可以提供更详细的帮助……?

24

我想在@Mark Rushakoff的回答中补充两点。当我调试的时候,发现把我调用open()时的buffering参数改成0非常有用。

sys.stdout = open(str(os.getpid()) + ".out", "a", buffering=0)

否则就会很麻烦,因为当你用tail -f查看输出文件时,结果可能会非常不稳定。设置buffering=0对于使用tail -f来说效果很好。

另外,为了完整起见,建议你也把sys.stderr重定向一下。

sys.stderr = open(str(os.getpid()) + "_error.out", "a", buffering=0)

还有,如果你愿意,可以把这些内容放到一个单独的进程类里,这样会更方便。

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'

这里有一个相关的代码片段

71

最简单的方法可能就是直接覆盖 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()

然后运行它:

$ 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

撰写回答