python - 在 Ubuntu 16.04 中使用 QueueHandler 复制日志消息
问题描述
我正在使用日志包从单个日志文件中的 3 个模块和多个进程进行日志记录,我有这三个模块:
#main.py
def worker_configurer(queue):
h = logging.handlers.QueueHandler(queue)
root = logging.getLogger()
root.addHandler(h)
root.setLevel(logging.DEBUG)
def listener_configurer():
log_file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'logging.conf')
logging.config.fileConfig(log_file_path)
def listener_process(queue, configurer):
configurer()
while True:
try:
record = queue.get()
if record is None:
break
recordName = record.name
logger = logging.getLogger(recordName)
logger.handle(record)
except Exception:
traceback.print_exc(file=sys.stderr)
if __name__=='__main__':
logging_queue = Queue(-1)
listener = Process(target=listener_process,
args=(logging_queue, listener_configurer))
listener.start()
worker_configurer(logging_queue)
logger = logging.getLogger('mylogger')
logger.info('This messgae from main process')
x = 5
y = 5
summation = a.A()
summation.toyFunc(x, y)
process = b.B(logging_queue)
process.start()
第二个模块,这个模块只记录一条消息:
#a.py
logger = logging.getLogger('mylogger.a')
class A():
def toyFunc(self, x, y):
logger.info('result: {}'.format(x+y))
第三个模块,该模块发送消息并休眠一会:
#b.py
logger = logging.getLogger('mylogger.b')
def worker_configurer(queue):
h = logging.handlers.QueueHandler(queue)
root = logging.getLogger()
root.addHandler(h)
root.setLevel(logging.DEBUG)
class B(Process):
def __init__(self, logging_queue, func=worker_configurer):
super(B, self).__init__()
self.logging_queue = logging_queue
self.func = func
def run(self):
self.func(self.logging_queue)
for i in range(10):
logger.info('hi: {}'.format(i))
time.sleep(5)
这是我的配置文件:
#logging.conf
[loggers]
keys=root,mylogger
[handlers]
keys=rootHandler,myloggerHandler
[formatters]
keys=formatter1
[logger_root]
#level=WARNING
level=ERROR
handlers=rootHandler
qualname=root
[logger_mylogger]
level=DEBUG
handlers=myloggerHandler
qualname=mylogger
propagate=0
[handler_rootHandler]
class=logging.handlers.TimedRotatingFileHandler
formatter=formatter1
args=("root.log", 'D', 1, 0, )
[handler_myloggerHandler]
class=logging.handlers.TimedRotatingFileHandler
formatter=formatter1
args=("mylogger.log", 'D', 1, 0, )
[formatter_formatter1]
format=%(asctime)s ~ %(levelname)s ~ %(process)d ~ %(module)s ~ %(funcName)s ~ %(message)s ~
这是输出:
2020-04-10 17:28:49,327 ~ INFO ~ 21820 ~ main ~ ~ 这个来自主进程的消息 ~
2020-04-10 17:28:49,328 ~ INFO ~ 21820 ~ a ~ toyFunc ~ 结果:10 ~
2020-04-10 17:28:49,340 ~ INFO ~ 21886 ~ b ~ 运行 ~ hi: 0 ~
2020-04-10 17:28:49,340 ~ INFO ~ 21886 ~ b ~ 运行 ~ hi: 0 ~
2020-04-10 17:28:54,347 ~ INFO ~ 21886 ~ b ~ 运行 ~ hi: 1 ~
2020-04-10 17:28:54,347 ~ INFO ~ 21886 ~ b ~ 运行 ~ hi: 1 ~
2020-04-10 17:28:59,353 ~ INFO ~ 21886 ~ b ~ 运行 ~ hi: 2 ~
2020-04-10 17:28:59,353 ~ INFO ~ 21886 ~ b ~ 运行 ~ hi: 2 ~
2020-04-10 17:29:04,358 ~ INFO ~ 21886 ~ b ~ 运行 ~ hi: 3 ~
2020-04-10 17:29:04,358 ~ INFO ~ 21886 ~ b ~ 运行 ~ hi: 3 ~
2020-04-10 17:29:09,362 ~ INFO ~ 21886 ~ b ~ 运行 ~ hi: 4 ~
2020-04-10 17:29:09,362 ~ INFO ~ 21886 ~ b ~ 运行 ~ hi: 4 ~
2020-04-10 17:29:14,362 ~ INFO ~ 21886 ~ b ~ 运行 ~ hi: 5 ~
2020-04-10 17:29:14,362 ~ INFO ~ 21886 ~ b ~ 运行 ~ hi: 5 ~
2020-04-10 17:29:19,368 ~ INFO ~ 21886 ~ b ~ 运行 ~ hi: 6 ~
2020-04-10 17:29:19,368 ~ INFO ~ 21886 ~ b ~ 运行 ~ hi: 6 ~
2020-04-10 17:29:24,373 ~ INFO ~ 21886 ~ b ~ 运行 ~ hi: 7 ~
2020-04-10 17:29:24,373 ~ INFO ~ 21886 ~ b ~ 运行 ~ hi: 7 ~
2020-04-10 17:29:29,379 ~ INFO ~ 21886 ~ b ~ 运行 ~ hi: 8 ~
2020-04-10 17:29:29,379 ~ INFO ~ 21886 ~ b ~ 运行 ~ hi: 8 ~
2020-04-10 17:29:34,382 ~ INFO ~ 21886 ~ b ~ 运行 ~ hi: 9 ~
2020-04-10 17:29:34,382 ~ INFO ~ 21886 ~ b ~ 运行 ~ hi: 9 ~
如您所见,消息与多处理类重复,如何解决这个问题?为了清楚起见,我需要先调用 A 然后再调用 B,我无法更改顺序,而且我必须使用 QueueHandler 从多个进程中记录(此代码来自冗长而复杂的代码,但我将其简化为清楚,但我在原始代码中遇到了这个问题)。当您在 Windows 上尝试此代码时,没有消息重复,但在 Linux(Ubuntu 16.04)上,消息是重复的!我不知道为什么,我需要在 Windows 中得到相同的结果(没有重复)。有什么可以帮忙的吗?这将不胜感激。谢谢!
解决方案
work_configurer 正在为每个进程实例化,我已经解决了这个问题,检查是否不应该有任何新的实例,如果已经存在一个工人
找到以下解决问题的代码:
def worker_configurer(queue):
h = logging.handlers.QueueHandler(queue)
root = logging.getLogger()
if not root.handlers:
root.addHandler(h)
root.setLevel(logging.DEBUG)
推荐阅读
- windows - 重命名文件夹会将文件位置更改为 \\?\D:User... 我无法打开它
- .net - 使用等待列表实现 Rest API
- excel - 仅将一行转置为一列
- python - 如何查找数据框中所有列之间的特征交互,Python?
- python - 尝试在 django 中为表单制作小部件时出错
- python - 如何根据日期时间过滤您的列表?
- r - 如何获取R中数据框列中唯一元素的频率?
- python - Python 错误“无效语法”和“名称 (...) 可能未定义”
- nginx - Kubernetes-nginx 中的 limit_except 不起作用
- reporting-services - 在多选中全选包括空白和空值