Код внутри словаря запускался без вызова - PullRequest
0 голосов
/ 06 августа 2020

Я создаю функцию для ведения журнала и использовал словарь для определения уровня журнала. Однако значение (код) внутри словаря выполнялось без его вызова.

def debug(level = 0, text = ''):
    logger = logging.getLogger()
    logger.setLevel(logging.DEBUG)
    Formatter = logging.Formatter('%(asctime)s %(levelname)-8s %(message)s', datefmt = '%Y-%m-%d %H:%M:%S')
    
    fileLog = logging.FileHandler('test.log')
    fileLog.setLevel(logging.DEBUG)
    fileLog.setFormatter(Formatter)
    logger.addHandler(fileLog)
    streamLog = logging.StreamHandler()
    streamLog.setLevel(logging.DEBUG)
    streamLog.setFormatter(Formatter)
    logger.addHandler(streamLog)
    log = str(sys._getframe(1).f_code.co_name + "  " + text)
    logLevel = {
        0: logger.debug(log),
        1: logger.info(log),
        2: logger.warning(log),
        3: logger.error(log),
        4: logger.critical(log)
    }
    logLevel.get(level, None)

def test():
    debug(0, "MESSAGE")

Как решить эту проблему?

Ответы [ 2 ]

1 голос
/ 06 августа 2020

Поскольку вы добавили «()» к logger.debug, вы сказали python, что хотите сохранить результат, возвращаемый этой функцией, в dict. Похоже, вы хотите сохранить функцию, а затем вызвать ее. Если это так, сделайте что-нибудь вроде этого.

logLevel = {
        0: logger.debug,
        1: logger.info,
        2: logger.warning,
        3: logger.error,
        4: logger.critical
}
logLevel.get(level, None)(log)    

Теперь вы сохраняете ссылку на функцию logger.debug, затем извлекаете ее из dict и затем вызываете.

Будьте осторожны, так как ваш возврат по умолчанию из get равен None, это вызовет ошибку, если его нет в dict.

1 голос
/ 06 августа 2020

Значения словаря должны быть оценены перед созданием словаря. Нет никакого пути обойти это.

Что вы можете сделать, так это обернуть значения в функцию, а затем вызвать эту функцию позже:

logLevel = {
    0: lambda: logger.debug(log),
    1: lambda: logger.info(log),
    2: lambda: logger.warning(log),
    3: lambda: logger.error(log),
    4: lambda: logger.critical(log)
}

log_f = logLevel[1]
log_f()  # Will call the "lambda: logger.info(log)" function.

Значения все еще оцениваются, но теперь это вычисляемая функция, а не код, который она содержит.

Этого также можно достичь, используя functools.partial

from functools import partial

logLevel = {
    0: partial(logger.debug, log),
    1: partial(logger.info, log),
    2: partial(logger.warning, log),
    3: partial(logger.error, log),
    4: partial(logger.critical, log)
}

log_f = logLevel[1]
log_f()

Ключевым моментом является необходимость отложить выполнение, и Обертка функции - самый простой (но не обязательно единственный) способ добиться этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...