#python #python-2.7 #logging #singleton #single-instance
#python #python-2.7 #ведение журнала #одноэлементный #одиночный экземпляр
Вопрос:
Я делаю этот проект на Python 2.7 и пытаюсь преобразовать эту функцию, которая возвращает объект ведения журнала. Я пытаюсь убедиться, что я могу использовать один и тот же экземпляр объекта через разные модули python, импортируя его без фактического создания новых экземпляров? Например, если я на самом деле импортирую модуль, в котором изначально был создан экземпляр, каждый раз, когда я его импортирую, создается новый экземпляр. Но я хочу использовать один и тот же исходный экземпляр во всех разных модулях, который был создан при первом запуске этого модуля, поскольку в моем файле журнала печатается несколько строк из-за нескольких экземпляров. Вот почему требуется одноэлементный класс в Python 2.7, но я не уверен, как преобразовать эту функцию в одноэлементный класс, чтобы она возвращала один экземпляр, и я мог использовать ее во всех своих различных модулях путем импорта без запуска новых экземпляров. Функция setLogger создает экземпляр logger, который вводит журналы в файл журнала file_name.
def setLogger(file_name):
logger = logging.getLogger(__name__)
if not getattr(logger, 'handler_set', None):
logger.setLevel(logging.INFO)
stream_handler = logging.StreamHandler()
file_handler = logging.FileHandler(file_name)
formatter = logging.Formatter('%(message)s')
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
logger.addHandler(stream_handler)
logger.setLevel(logging.INFO)
logger.propagate = False
logger.handler_set = True
return logger
Комментарии:
1. Эта функция уже ведет себя так, как вы ожидаете. Он всегда будет возвращать один и тот же объект logger, потому
logging.getLogger
что заботится об этом.2. @zvone Нет, это не так. Каждый раз, когда я вызываю эту функцию, она создает другой экземпляр. Я вызываю модуль, содержащий эту функцию, из разных модулей. Поэтому каждый раз, когда он вызывается, он создает другой экземпляр object . Но я хочу, чтобы один и тот же экземпляр повсюду
3.
__name__
это имя текущего модуля, поэтому для каждого модуля создается отдельный журнал. Вы можете использовать любую строку для имени. Попробуйтеlogger = logging.getLogger('MyLog')
для каждого вызова экземпляра, чтобы он каждый раз использовал один и тот же журнал.4. @Mike67 Я только что попробовал это, заменив name на ‘MyLog’, и это не сработало. Я явно распечатал созданные объекты, и все они были разными для разных модулей
Ответ №1:
Я не понимаю, почему при использовании одного и того же имени генерируются разные регистраторы.
Чтобы принудительно создать один экземпляр регистратора, получите регистратор один раз и сохраните его в глобальной переменной.
logger = None # global variable
def setLogger(file_name):
global logger
if logger == None:
print('Creating logger')
logger = logging.getLogger(__name__) # only run once
if not getattr(logger, 'handler_set', None):
........
return logger
Я настроил несколько модулей, чтобы сузить проблему.
— mylogger.py —
import logging
logger = None # global variable
def setLogger(file_name="LogOut.log"):
global logger
if logger == None:
print('Creating logger')
logger = logging.getLogger(__name__) # only run once
if not getattr(logger, 'handler_set', None):
logger.setLevel(logging.INFO)
stream_handler = logging.StreamHandler()
file_handler = logging.FileHandler(file_name)
formatter = logging.Formatter('%(message)s')
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
logger.addHandler(stream_handler)
logger.setLevel(logging.INFO)
logger.propagate = False
logger.handler_set = True
return logger
— modc.py —
import mylogger
def writelog():
print("Hello from " __name__)
print(__name__, 'LogID:', id(mylogger.setLogger()))
mylogger.setLogger().warning("Hello from " __name__)
— modb.py —
import mylogger
import modc
def writelog():
print("Hello from " __name__)
print(__name__, 'LogID:', id(mylogger.setLogger()))
mylogger.setLogger().warning("Hello from " __name__)
modc.writelog()
— moda.py —
import mylogger
def writelog():
print("Hello from " __name__)
print(__name__, 'LogID:', id(mylogger.setLogger()))
mylogger.setLogger().warning("Hello from " __name__)
import modb
import modc
writelog()
modb.writelog()
modc.writelog()
Я побежал moda.py
. Вот результат. Регистратор создается один раз, и каждый модуль использует один и тот же экземпляр регистратора. Все сообщения сохраняются в один и тот же файл. Обратите внимание, что я использую python 3.7.
Hello from modc
Creating logger
modc LogID: 1764613056456
Hello from modc
Hello from __main__
__main__ LogID: 1764613056456
Hello from __main__
Hello from modb
modb LogID: 1764613056456
Hello from modb
Hello from modc
modc LogID: 1764613056456
Hello from modc
Комментарии:
1. Эта логика имеет смысл, но вы должны понимать, что эта функция setLogger сама находится в модуле, который называется, скажем debugLogs.py . Итак, предположим, я пытаюсь настроить свой регистратор в файле с именем A.py Я импортирую debugLogs.py и настройте регистратор. Затем другой модуль B.py пытается настроить регистратор и вызывает debugLogs.py но даже для B.py регистратору изначально будет присвоено значение None, поэтому мы снова получаем разные объекты для разных файлов. Как вы считаете, логика должна быть такой, чтобы только при вызове из A.py logger настроен, и мы можем повторно использовать этот объект logger, созданный A.py через другие модули.