Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/344.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python多处理+;日志挂起_Python_Multiprocessing_Python Multiprocessing_Python Logging - Fatal编程技术网

Python多处理+;日志挂起

Python多处理+;日志挂起,python,multiprocessing,python-multiprocessing,python-logging,Python,Multiprocessing,Python Multiprocessing,Python Logging,我试图将Python日志框架配置为处理来自多处理.Pool的多个进程的消息。在大多数情况下,脚本将无限期地挂起,尽管已观察到一些其他行为,例如退出而不打印所有日志消息 我的实际代码更复杂,但我已将其简化为以下脚本,该脚本在我测试过的计算机上相当可靠地中断 #/usr/bin/env蟒蛇3 导入日志记录 导入日志记录处理程序 导入多处理 import multiprocessing.util L=logging.getLogger(_名称__) _全局队列=无 _globalListener=无

我试图将Python日志框架配置为处理来自
多处理.Pool
的多个进程的消息。在大多数情况下,脚本将无限期地挂起,尽管已观察到一些其他行为,例如退出而不打印所有日志消息

我的实际代码更复杂,但我已将其简化为以下脚本,该脚本在我测试过的计算机上相当可靠地中断

#/usr/bin/env蟒蛇3
导入日志记录
导入日志记录处理程序
导入多处理
import multiprocessing.util
L=logging.getLogger(_名称__)
_全局队列=无
_globalListener=无
def basicsetup():
全局队列
全球(globalListener)
cf=logging.Formatter(“[{levelname}]{created:.7f}{name}({process}{processName}):{message}”,style=“{”)
handler=logging.StreamHandler()
handler.setLevel(logging.DEBUG)
handler.setFormatter(cf)
#子进程应该使用队列将日志消息发送回主进程中的线程
_globalQueue=multiprocessing.Queue()
_globalListener=logging.handlers.QueueListener(\u globalQueue,handler,尊敬\u handler\u level=True)
_globalListener.start()
#配置主线程的日志记录
进程\设置(获取\队列())
def get_队列():
返回\u全局队列
def过程_设置(队列):
handler=logging.handlers.QueueHandler(队列)
logger=logging.getLogger()
logger.setLevel(logging.DEBUG)
logger.addHandler(处理程序)
def do_工作(i):
#做一些涉及日志的事情
#如果未记录任何内容,则工作正常
L.info(“你好{}来自MP”。格式(i))
如果名称=“\uuuuu main\uuuuuuuu”:
#其他启动方法也会失败,但这就是我在实际应用程序中使用的方法
多处理。设置启动方法(“生成”)
#可选,但更多调试信息
multiprocessing.util.log_to_stderr()
#配置日志记录
基本设置()
#设置多处理池,初始化每个子进程中的日志记录
使用multiprocessing.Pool(初始值设定项=process\u setup,initargs=(get\u queue(),)作为pl:
#100似乎很好,500大部分时间都失败了。
#如果再现错误时遇到问题,请尝试将此数字增加到1000
pl.map(工作范围(500))
如果_globalListener不是None:
#停止侦听器并加入它运行的线程。
#如果不这样做,退出时可能会丢失日志消息。
_globalListener.stop()
该脚本的思想是使用多处理队列和标准的logging QueueListener和QueueHandler类来处理登录子流程

预期行为-脚本应记录“Hello X from MP”1000次

实际行为-在某个点(不同的运行,有时根本不会发生)程序将无限期挂起。按Ctrl+C将产生回溯,一些日志消息,然后再次按Ctrl+C将终止脚本,并进行另一次回溯

运行失败时的输出示例(非常不确定,但通常与此类似):

#前几百行日志被删除-据我所知,没有多少有趣的内容丢失。
[信息]1590652696.6525624(72404~SpawnPoolWorker-4):议员你好456
[信息]1590652696.6525996(72404~SpawnPoolWorker-4):你好,议员457
[信息]1590652696.6526365(72404~SpawnPoolWorker-4):你好,议员458
[信息]1590652696.6526761(72404~SpawnPoolWorker-4):你好,议员459
[信息]1590652696.6527176(72404~SpawnPoolWorker-4):你好,议员460
[信息]1590652696.6527598(72404~SpawnPoolWorker-4):你好,议员461
^CTraceback(最近一次通话最后一次):
文件“/test_logging.py”,第62行,在
_globalListener.stop()
文件“/usr/lib/python3.8/logging/handlers.py”,第1508行,在stop中
self.\u thread.join()
文件“/usr/lib/python3.8/threading.py”,第1011行,在join中
self.\u等待状态锁定()
文件“/usr/lib/python3.8/threading.py”,第1027行,在等待状态锁中
elif lock.acquire(块,超时):
键盘中断
[INFO/MainProcess]进程正在关闭
[DEBUG/MainProcess]正在运行优先级>=0的所有“atexit”终结器
[DEBUG/MainProcess]告诉队列线程退出
[DEBUG/MainProcess]运行剩余的“atexit”终结器
[DEBUG/MainProcess]加入队列线程
^atexit中的错误。\u运行\u退出功能:
回溯(最近一次呼叫最后一次):
文件“/usr/lib/python3.8/multiprocessing/util.py”,第300行,在运行终结器中
终结器()
文件“/usr/lib/python3.8/multiprocessing/util.py”,第224行,在调用中__
res=self.\u回调(*self.\u args,**self.\u kwargs)
文件“/usr/lib/python3.8/multiprocessing/queues.py”,第195行,在_finalize_join中
thread.join()
文件“/usr/lib/python3.8/threading.py”,第1011行,在join中
self.\u等待状态锁定()
文件“/usr/lib/python3.8/threading.py”,第1027行,在等待状态锁中
elif lock.acquire(块,超时):
键盘中断
系统配置:我在Arch Linux上的Python3.8.3(到今天为止)和Fedora 30上的Python3.7.7上复制了这一点


如果您能深入了解这个问题,我将不胜感激。我已经为这个问题绞尽脑汁了一段时间。

我也遇到了这个问题。一个可能的解决方法是使用多处理队列来处理日志消息,所有工作人员都将日志消息传递给一个进程模块,并由一个进程模块记录,这样就取消了此和日志处理程序的设置可以通过使用
enqueue=True
参数使多处理安全

# First several hundred lines of logs removed - as far as I can tell, there's not much of interest missing.

[INFO] 1590652696.6525624 __mp_main__ (72404~SpawnPoolWorker-4): Hello 456 from MP
[INFO] 1590652696.6525996 __mp_main__ (72404~SpawnPoolWorker-4): Hello 457 from MP
[INFO] 1590652696.6526365 __mp_main__ (72404~SpawnPoolWorker-4): Hello 458 from MP
[INFO] 1590652696.6526761 __mp_main__ (72404~SpawnPoolWorker-4): Hello 459 from MP
[INFO] 1590652696.6527176 __mp_main__ (72404~SpawnPoolWorker-4): Hello 460 from MP
[INFO] 1590652696.6527598 __mp_main__ (72404~SpawnPoolWorker-4): Hello 461 from MP
^CTraceback (most recent call last):
  File "./test_logging.py", line 62, in <module>
    _globalListener.stop()
  File "/usr/lib/python3.8/logging/handlers.py", line 1508, in stop
    self._thread.join()
  File "/usr/lib/python3.8/threading.py", line 1011, in join
    self._wait_for_tstate_lock()
  File "/usr/lib/python3.8/threading.py", line 1027, in _wait_for_tstate_lock
    elif lock.acquire(block, timeout):
KeyboardInterrupt
[INFO/MainProcess] process shutting down
[DEBUG/MainProcess] running all "atexit" finalizers with priority >= 0
[DEBUG/MainProcess] telling queue thread to quit
[DEBUG/MainProcess] running the remaining "atexit" finalizers
[DEBUG/MainProcess] joining queue thread
^CError in atexit._run_exitfuncs:
Traceback (most recent call last):
  File "/usr/lib/python3.8/multiprocessing/util.py", line 300, in _run_finalizers
    finalizer()
  File "/usr/lib/python3.8/multiprocessing/util.py", line 224, in __call__
    res = self._callback(*self._args, **self._kwargs)
  File "/usr/lib/python3.8/multiprocessing/queues.py", line 195, in _finalize_join
    thread.join()
  File "/usr/lib/python3.8/threading.py", line 1011, in join
    self._wait_for_tstate_lock()
  File "/usr/lib/python3.8/threading.py", line 1027, in _wait_for_tstate_lock
    elif lock.acquire(block, timeout):
KeyboardInterrupt