将每个进程记录到不同的日志文件
Posted
技术标签:
【中文标题】将每个进程记录到不同的日志文件【英文标题】:Logging each process to a different log file 【发布时间】:2019-04-20 02:09:37 【问题描述】:我是 Python 的新手,记录多进程对我来说似乎很困惑。目前使用 Python 3.6.6
我创建了一个脚本来设置我的处理程序并允许我创建唯一的日志名称(我想要为每个进程创建)或使用主日志文件。
在控制台中我想显示警告和错误,在日志文件中我想跟踪调试消息。
logging_config.py
import logging
import sys
import os
import pathlib
CONSOLE_FORMATER = logging.Formatter("%(levelname)s - %(message)s")
FILE_FORMATTER = logging.Formatter("%(asctime)s - %(levelname)s - %(name)s.%(funcName)s:%(lineno)d - %(message)s'")
def getConsoleHandler():
consoleHandler = logging.StreamHandler(sys.stdout)
consoleHandler.setFormatter(CONSOLE_FORMATER)
consoleHandler.setLevel(logging.WARNING)
return consoleHandler
def getFileHandler(**kwargs):
path = createLogDir()
if 'logName' in kwargs:
logFile = path + "/" + kwargs['logName'] + ".log"
else:
logFile = path + "/deploy-orchestrator.log"
# fileHandler = logging.FileHandler(logFile, mode='w')
fileHandler = logging.FileHandler(logFile)
fileHandler.setFormatter(FILE_FORMATTER)
fileHandler.setLevel(logging.DEBUG)
return fileHandler
def createLogDir():
path = f"os.path.dirname(os.getcwd())/logs" # get working parent dir
pathlib.Path(path).mkdir(exist_ok=True) # create /logs dir, if it exists throw no errors
return path
# if uniqueLog is set to true then a log will be made with the logger name
def getLogger(loggerName, **kwargs):
logger = logging.getLogger(loggerName)
logger.addHandler(getConsoleHandler())
if 'uniqueLog' in kwargs and kwargs['uniqueLog'] is True:
logger.addHandler(getFileHandler(logName=loggerName))
else:
logger.addHandler(getFileHandler())
logger.setLevel(logging.DEBUG)
logger.propagate = False
return logger
对于简单的日志记录,我可以导入我的 logging_config 并记录我需要的任何内容。
simple_example.py
import logging_config as logs
logger = logs.getLogger(__name__)
logger.debug("This works just fine and goes into the default log file")
logger.warning("This works just fine and goes to console and the log file")
现在是什么不起作用。
multiprocess_parent.py
from multiprocessing import Process
processes = []
for child_name in children:
process_child = ProcessChild(child_name)
p = Process(target=process_child.worker, args=(widget))
processes.append(p)
p.start()
for p in processes:
p.join()
multiprocess_child.py
import logging_config as logs
class ProcessChild:
logger = None
def __init__(self, child_name):
self.child_name = child_name
self.logger = logging.getLogger(child_name, uniqueLog=True) # Each child getting it's own log file
def worker(widget):
logger.info("This EXPLODES")
我得到的错误是ForkingPickler(file, protocol).dump(obj)
TypeError: can't pickle _thread.RLock objects
它来自p.start()
这一行
那么在这种情况下,您如何为每个进程写入单独的日志文件呢?我最初的想法是在这里创建一个错误的logging_config.py
吗?我这样做是为了让多个模块可以使用相同的配置。
另一方面,日志文件本身是用正确的名称正确创建的,当每个进程尝试写入正确的日志文件时,就会发生此错误。
【问题讨论】:
【参考方案1】:我对 Python 编码也很陌生。我可能会离开,但是当您定义 worker 方法时,它看起来像在您的 multiprocess_child.py 中,logger 没有被正确调用。
例如,如果您想在定义的方法中使用 ProcessChild 类下的全局变量 logger,则可以使用 ProcessChild.logger (见下文)。
logger = None
def __init__(self, child_name):
self.child_name = child_name
ProcessChild.logger = logging.getLogger(child_name, uniqueLog=True)
def worker(widget):
ProcessChild.logger.info("This EXPLODES")
【讨论】:
以上是关于将每个进程记录到不同的日志文件的主要内容,如果未能解决你的问题,请参考以下文章
Monolog:将不同通道和多个处理程序记录到分组日志文件 + 专用日志文件