#python #python-3.x
Вопрос:
Я сталкиваюсь со странным вопросом о logging
библиотеке при использовании multiprocessing
.
Первый пример (неверный):
import multiprocessing
import logging
import time
class A:
def __init__(self):
self.logger = None
self.v = "v1"
def run(self):
# start a new process here
p = multiprocessing.Process(target=self.work, name="sub-process")
p.start()
def work(self):
i = 0
# print info of logger object
print(f"v: {self.v}; logger: {self.logger}; handler:{self.logger.handlers}")
while True and i < 10:
name = multiprocessing.current_process().name
self.logger.info(f"current name: {name} v : {self.v}")
time.sleep(0.5)
i = 1
class B(A):
def __init__(self):
super(B, self).__init__()
self.v = "v2"
# if init logger object inside class
# then something wrong happens...
logger = logging.getLogger()
ch = logging.FileHandler("test.log")
ch.setFormatter(logging.Formatter('%(asctime)s %(levelname)s %(funcName)s(): %(message)s'))
ch.setLevel(logging.DEBUG)
logger.setLevel(logging.DEBUG)
logger.addHandler(ch)
logger.addHandler(logging.StreamHandler())
self.logger = logger
self.logger.info("B init success")
if __name__ == '__main__':
b = B()
b.run()
и он выводит неверно:
B init success # this line is the output of logger in __init__
v: v2; logger: <RootLogger root (WARNING)>; handler: [] # this line is the output of print function in work
Мы видим, что logger
во время работы метода он изменился на необработанный объект корневого регистратора(с обработчиком по умолчанию WARNING
и пустым обработчиком) work
.
Но все идет хорошо, когда я меняю местоположение инициализации регистратора.
import multiprocessing
import logging
import time
# if init logger object outside class
# then all goes well
logger = logging.getLogger()
ch = logging.FileHandler("test.log")
ch.setFormatter(logging.Formatter('%(asctime)s %(levelname)s %(funcName)s(): %(message)s'))
ch.setLevel(logging.DEBUG)
logger.setLevel(logging.DEBUG)
logger.addHandler(ch)
logger.addHandler(logging.StreamHandler())
class A:
def __init__(self):
self.logger = None
self.v = "v1"
def run(self):
# start a new process here
p = multiprocessing.Process(target=self.work, name="sub-process")
p.start()
def work(self):
i = 0
# print info of logger object
print(f"v: {self.v}; logger: {self.logger}; handler:{self.logger.handlers}")
while True and i < 10:
name = multiprocessing.current_process().name
self.logger.info(f"current name: {name} v : {self.v}")
time.sleep(0.5)
i = 1
class B(A):
def __init__(self):
super(B, self).__init__()
self.v = "v2"
self.logger = logger
self.logger.info("B init success")
if __name__ == '__main__':
b = B()
b.run()
И на этот раз результаты верны!( logger
объект просто я определяю в коде)
B init success
# the following line is output of print function
current name: sub-process v : v2
v: v2; logger: <RootLogger root (DEBUG)>; handler:[<FileHandler /Users/zjj/test.log (DEBUG)>, <StreamHandler <stderr> (NOTSET)>]
current name: sub-process v : v2
current name: sub-process v : v2
current name: sub-process v : v2
current name: sub-process v : v2
current name: sub-process v : v2
current name: sub-process v : v2
current name: sub-process v : v2
current name: sub-process v : v2
current name: sub-process v : v2
Но в моем проекте я должен инициализировать объект регистратора, пока не получу некоторые параметры от __init__
метода,есть ли способ устранить эту проблему(неправильная версия)?
Спасибо!
Комментарии:
1. в Linux Mint обе версии дают один и тот же результат с
v: v2; logger: <RootLogger root (DEBUG)>; handler:[<FileHandler /Users/zjj/test.log (DEBUG)>, <StreamHandler <stderr> (NOTSET)>]
2. Я подтверждаю, что первый сценарий дает «неправильные» результаты под Windows, и он работает, как и ожидалось, на Raspian. В Windows, в методе работы, мы используем другой регистратор, подтвержденный печатью(идентификатор(self.logger)). В Raspbian идентификаторы те же самые. Понятия не имею, почему.
3. Моя система-m1 Mac, так что это системно. Mac и Windows дадут неправильные результаты, система Linux может поступить правильно.