我有一个正在进行的python3(3.4.5)项目,该项目利用multiprocessing.Pool
通过4个工人运行大约50多个工作。我使用logging.handlers.QueueListener
进行了单独的流程设置,因此我可以通过与Queue
一起使用的multiprocessing.Manager()
将全局内容记录到单个文件中。所以基本上流程是这样的
Queue
创建multiprocessing.Manager()
QueueListener
监听我刚刚为全局日志创建的Queue
,开始专用的日志记录过程。 (我也尝试过使用主程序中的一个线程,但结果相同。)multiprocessing.Pool
来处理各个作业,将先前创建的Queue
传递给它们,并传递必要的配置信息以运行和设置其日志记录(有一个全局日志,以及每个作业的单个日志详细信息)。作业以map_async
开始。尽管我在某些作业上经常遇到间歇性错误,通常在其中一个作业上有一个错误(每次都不同),偶尔有两个相同的错误,或者为零。据我所知,导致错误的不是作业中的代码,而是multiprocessing
或logging
设置中的错误。这是我遇到的错误的示例:
--- Logging error ---
Traceback (most recent call last):
File "/usr/lib64/python3.4/logging/handlers.py", line 1347, in emit
self.enqueue(self.prepare(record))
File "/usr/lib64/python3.4/logging/handlers.py", line 1313, in enqueue
self.queue.put_nowait(record)
File "<string>", line 2, in put_nowait
File "/usr/lib64/python3.4/multiprocessing/managers.py", line 731, in _callmethod
conn.send((self._id, methodname, args, kwds))
File "/usr/lib64/python3.4/multiprocessing/connection.py", line 206, in send
self._send_bytes(ForkingPickler.dumps(obj))
File "/usr/lib64/python3.4/multiprocessing/connection.py", line 413, in _send_bytes
self._send(chunk)
File "/usr/lib64/python3.4/multiprocessing/connection.py", line 369, in _send
n = write(self._handle, buf)
TypeError: an integer is required (got type NoneType)
Call stack:
File "./sampling__test__py.py", line 100, in <module>
run_pool = multiprocessing.Pool(4)
File "/usr/lib64/python3.4/multiprocessing/context.py", line 118, in Pool
context=self.get_context())
File "/usr/lib64/python3.4/multiprocessing/pool.py", line 168, in __init__
self._repopulate_pool()
File "/usr/lib64/python3.4/multiprocessing/pool.py", line 233, in _repopulate_pool
w.start()
File "/usr/lib64/python3.4/multiprocessing/process.py", line 105, in start
self._popen = self._Popen(self)
File "/usr/lib64/python3.4/multiprocessing/context.py", line 267, in _Popen
return Popen(process_obj)
File "/usr/lib64/python3.4/multiprocessing/popen_fork.py", line 21, in __init__
self._launch(process_obj)
File "/usr/lib64/python3.4/multiprocessing/popen_fork.py", line 77, in _launch
code = process_obj._bootstrap()
File "/usr/lib64/python3.4/multiprocessing/process.py", line 254, in _bootstrap
self.run()
File "/usr/lib64/python3.4/multiprocessing/process.py", line 93, in run
self._target(*self._args, **self._kwargs)
File "/usr/lib64/python3.4/multiprocessing/pool.py", line 119, in worker
result = (True, func(*args, **kwds))
File "/usr/lib64/python3.4/multiprocessing/pool.py", line 44, in mapstar
return list(map(*args))
File "/home/username/value_check.py", line 338, in value_check
global_logger.info("SplitTime: {str_timeDelta} -- COMPLETED: {Check_Name} --- Total Txn Count: {var_Total_Txn_Count} --- Criteria Txn Count: {var_Criteria_Txn_Count} --- Threshold: {Threshold} --- Low_Vol Threshold: {LowVolThresh}".format(str_timeDelta = timeDelta(datetime.now() - YAML_Config['start_time']), **YAML_Config))
Message: 'SplitTime: 00:01:05,031 -- COMPLETED: ALPHA_CHECK --- Total Txn Count: 1234--- Criteria Txn Count: 0 --- Threshold: 10 --- Low_Vol Threshold: 0'
Arguments: None
代码中的错误指的是代码中的一个日志记录对象,但是即使我将try/except
逻辑放在调用周围,它也无能为力,该错误似乎发生在上游。我还尝试将正在记录的内容从格式化的字符串更改为只是一个简单的字符串,但无济于事。似乎各个作业在某个途中要么失去了与Queue
的连接,要么Queue
中的某项出现故障并引起了问题。
有什么想法吗?我一直在努力获取较新版本的Python,由于多种原因(特别是f字符串),这将是有益的,但是我不知道这是否可以解决此问题,并且我已经用完了故障排除思路。
答案 0 :(得分:2)
即使我在调用中加入了try / except逻辑,它也无济于事。
这可能是因为,如果日志记录程序包遇到与日志记录本身有关的异常,它将打印回溯,但不会引发异常本身。 logging.Handler.handleError
的文档字符串中对此有更充分的说明。
一个开始的地方是通过设置:
logging.raiseExceptions = True
如果模块级别的属性raiseExceptions为False,则异常会被忽略。
如果这没有帮助,则可以在.emit()
的代码中调用import pdb; pdb.set_trace()
;像这样:
def emit(self, record):
try:
msg = self.format(record)
stream = self.stream
stream.write(msg)
stream.write(self.terminator)
self.flush()
except Exception as e:
import pdb; pdb.set_trace() # < ---
self.handleError(record)
其中record
将是LogRecord
实例。通常,当我看到弹出日志错误时,这是因为我为给定的格式字符串使用了错误数量的args,但是检查record
对象应该希望告诉您更多信息。
最后,从调用堆栈中可以看到日志记录调用本身:
global_logger.info(
"SplitTime: {str_timeDelta} -- "
"COMPLETED: {Check_Name} --- "
"Total Txn Count: {var_Total_Txn_Count} --- "
"Criteria Txn Count: {var_Criteria_Txn_Count} --- "
"Threshold: {Threshold} --- "
"Low_Vol Threshold: {LowVolThresh}".format(
str_timeDelta = timeDelta(datetime.now() - YAML_Config['start_time']), **YAML_Config))
很难说出最终导致异常的确切原因,因为该字符串似乎已被完全格式化。 (尽管看不到YAML_Config
。)
无论如何,一个建议是:您可以利用日志记录的“惰性”字符串格式而不是像目前那样使用str.format()
。 str.format()
调用将尽快得到评估,而如果将kwargs传递给global_logger.info()
,则日志记录包将等待对其进行评估,直到必须进行评估。