记录器创建多个文件

时间:2014-07-30 03:50:56

标签: python logging python-3.x multiprocessing

以下代码会创建3个或4个日志文件。如何编写以便在保留文件名格式的同时只创建一个文件?此外,这似乎是Windows唯一的问题。当我在RHEL 5.3盒子上运行它甚至将nproc设置为1000时,我只获得1个日志文件。 [Python 3.4.1]

import datetime, logging, multiprocessing, os.path, time

logging.basicConfig(level=logging.DEBUG, format="%(asctime)-4s %(process)6s  %(message)s", datefmt="%m-%d %H:%M:%S",
    filename="test_%s.log"%(datetime.datetime.today().strftime("%Y%m%d-%H%M%S")))

def worker(n):
    logging.info("before")
    time.sleep(n)
    logging.info("after")

if __name__=='__main__':
    nproc = 40
    pool = multiprocessing.Pool(processes=nproc)
    pool.map(worker, (6,)*nproc)

2 个答案:

答案 0 :(得分:1)

原始答案:将logging.basicConfig电话放入您的主要声明中。

新答案:将日志记录调用添加到worker函数的开头。您可以将其放入名为setup_logging的函数中以供将来更改。我之前的回答可能不会起作用,因为工人们没有设置日志记录。

multiprocessing运行新目标时,它必须启动一个全新的解释器,然后加载具有要运行的函数的模块。在您进行日志记录调用的地方,每次加载模块时都会运行它。我猜测它只在linux上创建一个文件就是运气。

我应该注意记录的正常模式(至少我使用的)是:

import logging

log = logging.getLogger(__name__)

# Code
def a_func():
    log.debug("This is my message")

if __name__ == "__main__":
    logging.basicConfig(...)
    a_func()

编辑:如果它不清楚我的意思是运气,我的意思是你要创建一个包含当前日期/时间的文件名,这样就可以开始同时启动多个进程时间就是运气。如果操作系统需要很长时间才能启动X个工作人员,那么您将获得不同的文件名。在Linux上,它可以做一些聪明的事情,同时加载所有的解释器/模块,然后调用该函数。

您的代码:我很抱歉在累了时编写stackoverflow答案。我之前的解决方案并没有真正解决问题。这样做:

import datetime, logging, multiprocessing, os.path, time

def worker(args):
    # it's not simple to pass more than one argument so we expand the tuple here
    n, log_filename = args
    logging.basicConfig(level=logging.DEBUG,
            format="%(asctime)-4s %(process)6s  %(message)s",
            datefmt="%m-%d %H:%M:%S",
            filename=log_filename)

    logging.info("before")
    time.sleep(n)
    logging.info("after")

if __name__=='__main__':
    filename="test_%s.log" % (datetime.datetime.today().strftime("%Y%m%d-%H%M%S"),)
    nproc = 40
    pool = multiprocessing.Pool(processes=nproc)
    pool.map(worker, ((6, filename),)*nproc)

答案 1 :(得分:0)

您需要做几件事:

  1. 确保您创建一次文件名,并在所有进程中共享它。 daveydave400在他的回答中说明了这一点。
  2. 确保所有进程的写入操作都已同步。如果你不这样做,你的工作进程将尝试同时写入日志,这可能导致一个写入stomping另一个。另一个答案中没有涉及避免这种情况。
  3. logging模块在​​内部使用threading.RLock来同步写入,但这不是进程安全的:每个进程都有自己的Rlock,对其他进程一无所知。因此,您需要创建自己的logging.Handler使用进程安全锁,然后与池中的每个进程共享该锁。我们可以利用initializer的{​​{1}} / initargs关键字参数来实现这一目标。我们只需将在所有工作进程中创建相同记录器所需的所有参数传递给multiprocessing.Pool函数,然后为每个进程构建一个全局initializer对象。

    这是一个有效的例子:

    logging.Logger