在Python中记录不同进程的单独文件

时间:2013-08-14 20:06:23

标签: python logging multiprocessing

在Python中使用多处理模块时,我看到了一些关于将来自不同进程的日志放在一起的问题。我想做相反的事情,为不同的进程生成单独的日志文件,并且它们应该记录调用其他模块时发生的所有事情而不会被破坏。在下面的例子中,我有一个主程序(main.py)和两个模块(module1.py和module2.py),我希望主记录器(mainlog)写入stdout,它做得很好。我还想为每个进程分别创建一个文件,包括从module1和module2进行日志记录。

main.py:

import logging
import multiprocessing as mpr
import module1
import sys

mainlog = logging.getLogger("main")
h = logging.StreamHandler(sys.stdout)
mainlog.addHandler(h)
logging.root.setLevel(logging.DEBUG)

for i in xrange(0,3):
    mainlog.info("Starting process ... %s", i)
    log = logging.getLogger("module1")
    h = logging.FileHandler("process_{0}.log".format(i))
    fmt = logging.Formatter(fmt="%(levelname)-10s:%(filename)-20s:%(message)s")
    h.setFormatter(fmt)
    log.addHandler(h)
    log.setLevel(logging.DEBUG)
    p = mpr.Process(target=module1.do_something, args=(i,))
    p.start()

module1.py:

import logging
import module2

log = logging.getLogger("module1")

def do_something(i):

    for j in xrange(0,100):
        log.debug("do something. process %2s. iteration %2s", i,j)
        module2.multiply(j,2)

还有一个module2.py:

import logging
log = logging.getLogger("module2")

def multiply(x,y):
    log.debug("... multiplying %s x %s = %s", x,y, x*y)
    return x*y

相反,我得到以下输出:

Starting process ... 0
Starting process ... 1
No handlers could be found for logger "module2"
Starting process ... 2
No handlers could be found for logger "module2"
No handlers could be found for logger "module2"

3个单独的日志记录文件(process_0.log,...),它们包含来自所有进程的消息,而不是只有一个。没有记录任何来自module2.py的内容。我做错了什么?

2 个答案:

答案 0 :(得分:2)

我最终创建了logging.Logger的子类来管理记录到main和记录到磁盘之间的切换。现在我可以在进程中进行必要的切换:

import logging
import sys


class CGLogger(logging.Logger):
    def __init__(self,name):
        logging.Logger.__init__(self,name)
        self.mainhandler = logging.StreamHandler(sys.stdout)
        self.addHandler(self.mainhandler)

    def stop_main_logging(self):
        self.removeHandler(self.mainhandler)

    def log_to_file(self, fn):
        self.filehandler = logging.FileHandler(fn)
        self.addHandler(self.filehandler)

    def stop_logging_to_file(self):
        self.removeHandler(self.filehandler)

    def restart_main_logging(self):
        self.addHandler(self.mainhandler)

    def switch_to_file_logging(self, fn):
        self.stop_main_logging()
        self.log_to_file(fn)

    def switch_to_main_logging(self):
        self.stop_logging_to_file()
        self.restart_main_logging(fn)

logging.setLoggerClass(CGLogger)

答案 1 :(得分:1)

您需要在子进程中配置日志记录。他们从干净的平板开始,并且没有配置日志记录。你有机会在Windows上吗?几乎没有任何内容从父进程继承到Windows中的子进程,而在POSIX上,fork()语义可以允许继承某些内容。