我是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
的初衷吗?我这样做是为了使多个模块可以使用相同的配置。
另外要注意的是,日志文件本身是使用正确的名称正确创建的,这是每个进程尝试将其写入正确的日志文件时发生的错误。
答案 0 :(得分:0)
我对使用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")