我正在将一个程序转换为多进程,并且需要能够从主进程和子进程将日志记录到单个循环日志中。我尝试使用python烹饪书Logging to a single file from multiple processes中的第二个示例,它启动作为主进程一部分运行的logger_thread
,从子进程添加到的队列中获取日志消息。这个例子的工作原理和is一样好,如果我切换到RotatingFileHandler也可以。在
但是,如果我将其更改为在子进程之前启动logger_thread
(这样我也可以从主进程记录日志),那么一旦日志旋转,所有后续日志记录都会生成一个带有WindowsError: [Error 32] The process cannot access the file because it is being used by another process
的回溯。在
换句话说,我改变了第二个例子中的代码
workers = []
for i in range(5):
wp = Process(target=worker_process, name='worker %d' % (i + 1), args=(q,))
workers.append(wp)
wp.start()
logging.config.dictConfig(d)
lp = threading.Thread(target=logger_thread, args=(q,))
lp.start()
为此:
^{pr2}$然后用logging.FileHandler
替换logging.handlers.RotatingFileHandler
(用一个非常小的maxBytes
进行测试),然后我遇到了这个错误。在
我使用的是Windows和python2.7。QueueHandler
不是stdlib til python3.2的一部分,但是我从Gist复制了源代码,它说这样做是安全的。在
我不明白为什么首先启动侦听器会有什么不同,也不明白为什么除main之外的任何进程都会尝试访问该文件。在
永远不要在子进程之前启动任何线程。当Python分叉时,线程和IPC状态不会总是被正确地复制。在
这方面有很多资源,只需google搜索fork和threads。有些人声称他们能做到,但我不清楚它是否能正常工作。在
先开始你所有的程序。在
附加信息示例:
Status of mixing multiprocessing and threading in Python
https://stackoverflow.com/a/6079669/4279
在您的情况下,可能是复制的打开文件句柄有问题,但是您仍然应该在线程之前(以及在打开以后要销毁的任何文件之前)启动子进程。在
fantabolous从评论中总结了一些经验法则:
子进程必须在同一进程创建的任何线程之前启动。
在多处理.池同时创建子进程和线程,因此不能在第一个进程或池之后创建其他进程或池。
在创建进程或池时,文件不应已打开。(在某些情况下,这是可以的,但不可以,例如,如果以后要删除某个文件。)
子流程可以创建自己的线程和进程,并应用上面的相同规则。
首先启动所有进程是最简单的方法
因此,您可以简单地创建自己的文件日志处理程序。我还没有看到日志由于多处理而变得混乱,所以文件日志轮换似乎是个大问题。只需在主目录中执行此操作,就不必更改其他日志记录
我愿意猜测每次尝试旋转时锁定可能会减慢日志记录速度,但在这种情况下,我们需要牺牲性能来保证正确性。在
相关问题 更多 >
编程相关推荐