python - Python 多处理 log_to_stderr 在 Windows 上重复
问题描述
我正在关注使用多处理进行日志记录的文档,但我看到工作人员在每个子进程中创建了两个日志。我在某个地方犯了一个愚蠢的错误吗?
环境:
Python 3.6.1 |Anaconda 自定义(64 位)| (默认,2017 年 5 月 11 日,13:25:24)[MSC v.1900 64 位 (AMD64)] 在 win32 上
代码(编辑以修复@georgexsh 推荐的范围问题):
import logging
import multiprocessing
logger = multiprocessing.log_to_stderr(logging.INFO)
def test(i):
logger.info(f'worker processing {i}')
if __name__ == '__main__':
with multiprocessing.Pool() as pool:
metrics = pool.map(test, range(20))
记录输出:
[INFO/SpawnPoolWorker-2] child process calling self.run()
[INFO/SpawnPoolWorker-2] child process calling self.run()
[INFO/SpawnPoolWorker-2] worker processing 0
[INFO/SpawnPoolWorker-3] child process calling self.run()
[INFO/SpawnPoolWorker-3] child process calling self.run()
[INFO/SpawnPoolWorker-2] worker processing 0
[INFO/SpawnPoolWorker-1] child process calling self.run()
[INFO/SpawnPoolWorker-3] worker processing 1
[INFO/SpawnPoolWorker-2] worker processing 2
[INFO/SpawnPoolWorker-1] child process calling self.run()
[INFO/SpawnPoolWorker-6] child process calling self.run()
[INFO/SpawnPoolWorker-3] worker processing 1
[INFO/SpawnPoolWorker-4] child process calling self.run()
[INFO/SpawnPoolWorker-2] worker processing 2
[INFO/SpawnPoolWorker-5] child process calling self.run()
[INFO/SpawnPoolWorker-7] child process calling self.run()
[INFO/SpawnPoolWorker-1] worker processing 3
[INFO/SpawnPoolWorker-6] child process calling self.run()
[INFO/SpawnPoolWorker-3] worker processing 4
[INFO/SpawnPoolWorker-4] child process calling self.run()
[INFO/SpawnPoolWorker-2] worker processing 5
[INFO/SpawnPoolWorker-5] child process calling self.run()
[INFO/SpawnPoolWorker-7] child process calling self.run()
[INFO/SpawnPoolWorker-1] worker processing 3
[INFO/SpawnPoolWorker-6] worker processing 6
[INFO/SpawnPoolWorker-3] worker processing 4
...
[INFO/SpawnPoolWorker-5] worker processing 16
[INFO/SpawnPoolWorker-2] worker processing 12
[INFO/SpawnPoolWorker-7] worker processing 17
[INFO/SpawnPoolWorker-1] worker processing 18
[INFO/SpawnPoolWorker-6] worker processing 13
[INFO/SpawnPoolWorker-3] worker processing 19
[INFO/SpawnPoolWorker-8] worker processing 14
[INFO/SpawnPoolWorker-4] worker processing 15
[INFO/SpawnPoolWorker-5] worker processing 16
[INFO/SpawnPoolWorker-7] worker processing 17
[INFO/SpawnPoolWorker-1] worker processing 18
[INFO/SpawnPoolWorker-3] worker processing 19
[INFO/SpawnPoolWorker-2] process shutting down
[INFO/SpawnPoolWorker-6] process shutting down
[INFO/MainProcess] process shutting down
解决方案
移动logger = multiprocessing.log_to_stderr()
到全局范围,而不是工作函数内部。以确保它只调用一次。因为每次log_to_stderr
被调用,它都会向记录器添加一个新的处理程序:
def test(i):
logger.info('worker processing %s', i)
if __name__ == '__main__':
logger = multiprocessing.log_to_stderr(logging.INFO)
请注意,在 windows 下,由于没有fork()
,当创建子进程以重建上下文时,整个模块会再次执行,您可以使用Pool
'sinitializer
初始化记录器,它只运行一次前子进程:
logger = None
def test(i):
logger.info('worker processing %s', i)
def initializer(level):
global logger
logger = multiprocessing.log_to_stderr(level)
if __name__ == '__main__':
pool = multiprocessing.Pool(4, initializer=initializer, initargs=(logging.INFO,))
metrics = pool.map(test, range(20))
推荐阅读
- android - InjectPresenter 在带有库 Moxy 的 Activity 中不起作用
- python - 计数 Game Try/Except 并计算用户尝试次数
- stylelint - 过时的 CSS 属性的规则?
- python - Python selenium 不显示表格内容
- java - 我的机器人正在为 1 个请求发送多条消息
- django - 在 Amazon Elastic Beanstalk 上安装 Anaconda 以在 Django 应用程序中使用
- java - 当值以数字开头时,添加 getter 方法会禁止解析
- scala - spark - 在不使用案例类的情况下为 scala 模拟 pyspark asDict()
- android - Kotlin 片段 NullPointerException
- python - 脚本以交错顺序打印 - 可能存在线程安全问题