【发布时间】:2020-09-30 23:18:18
【问题描述】:
我有一个单线程 Python 应用程序。关闭此应用程序的标准方法是向其发送 SIGINT 并让各种 with: 和 try: finally: 块处理安全和优雅的关闭。但是,这会导致日志文件不可读,因为您只是开始查看来自处理程序的消息,而没有明确指示发生了什么或关闭的原因。
我尝试通过添加一个简单的信号处理程序来解决这个问题,该处理程序会在引发KeyboardInterrupt 之前记录接收到的信号,如下所示:
def log_and_exit_handler(signum, stack):
logger.info(f"Terminating due to signal {_signal.Signals(signum)}", stack_info=True)
raise KeyboardInterrupt()
_signal.signal(_signal.SIGINT, log_and_exit_handler)
但是,在测试它时,我收到了一个日志错误:
--- Logging error ---
Traceback (most recent call last):
File "/usr/local/lib/python3.7/logging/__init__.py", line 1029, in emit
self.flush()
File "/usr/local/lib/python3.7/logging/__init__.py", line 1009, in flush
self.stream.flush()
RuntimeError: reentrant call inside <_io.BufferedWriter name='<stderr>'>
Call stack:
[REDACTED]
File "[REDACTED]", line 485, in _save_checkpoint
_logger.info(f"Checkpoint saved")
File "/usr/local/lib/python3.7/logging/__init__.py", line 1378, in info
self._log(INFO, msg, args, **kwargs)
File "/usr/local/lib/python3.7/logging/__init__.py", line 1514, in _log
self.handle(record)
File "/usr/local/lib/python3.7/logging/__init__.py", line 1524, in handle
self.callHandlers(record)
File "/usr/local/lib/python3.7/logging/__init__.py", line 1586, in callHandlers
hdlr.handle(record)
File "/usr/local/lib/python3.7/logging/__init__.py", line 894, in handle
self.emit(record)
File "/usr/local/lib/python3.7/logging/__init__.py", line 1029, in emit
self.flush()
File "/usr/local/lib/python3.7/logging/__init__.py", line 1009, in flush
self.stream.flush()
File "[REDACTED]", line 203, in log_and_exit_handler
logger.info("Terminating due to signal {signal_}".format(signal_=signal_), stack_info=True)
Message: 'Terminating due to signal 2'
Arguments: ()
显然,收到信号时,应用程序已经在输出日志消息,logging 模块不可重入。
我是否可以使用任何变通方法或替代方法来安全地完成我在收到信号时记录信号的目标?
【问题讨论】:
-
我遇到了同样的问题,最终使用 asyncio 模块处理每个信号
-
@AlejandroKaspar 你能详细说明一下吗?
标签: python python-3.x logging signals