为什么 xlwings 禁止记录到文件
why xlwings suppresses logging to a file
在我的 app.py
模块中,我设置了一个带有控制台和文件处理程序的记录器,如下所示:
import logging
logger = logging.getLogger('app')
logger.setLevel(logging.DEBUG)
console_handler = logging.StreamHandler()
file_handler = logging.FileHandler('gsam_log.txt')
console_handler.setLevel(logging.INFO)
file_handler.setLevel(logging.INFO)
c_formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
f_formatter = logging.Formatter('%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
console_handler.setFormatter(c_formatter)
file_handler.setFormatter(f_formatter)
logger.addHandler(console_handler)
logger.addHandler(file_handler)
如果我在 Python 控制台中工作并且我这样做:from app import logger
它按预期工作 - 打印到控制台和文件。我想使用这个记录器从我的 xlwings
潜艇(用 @xw.sub
装饰)记录。但出于某种原因,日志只发送到控制台而不是文件。下面是来自 test.py
模块的代码,我通过 xlwings.
将其导入为 UDF 模块
from app import logger
import xlwings as xw
@xw.sub
def test():
logger.debug('test')
logger.info('test')
logger.warning('test')
我不太熟悉 xlwings
的工作原理,但由于 logging
模块的工作原理错综复杂,我建议不要在模块的全局范围内创建记录器,而是根据需要懒惰地创建它们。
在许多情况下,在全局范围内创建的日志是在之前创建的,任何代码都是运行。然后,其他一些代码会重新配置日志记录,这会导致删除现有日志并忘记其配置。这就是 disable_existing_loggers=False
参数存在于 logging.config
函数(例如 https://docs.python.org/2/library/logging.config.html#logging.config.fileConfig)的原因。
要查看是否是这种情况,我建议将您的日志定义代码移动到一个函数中,并根据需要调用它,例如:
导入日志记录
# app.py
_logger = None
def get_logger():
global _logger
if _logger is None:
_logger = logging.getLogger('app')
_logger.setLevel(logging.DEBUG)
# ... continue to define your logger ...
return _logger
然后在你的函数中:
from app import get_logger
import xlwings as xw
@xw.sub
def test():
logger = get_logger()
logger.debug('test')
logger.info('test')
logger.warning('test')
需要注意的是,这不是使用日志记录的 "cleanest" 方式(通常这不是必需的)但是如果问题真的是其他一些模块扰乱了日志记录配置,这可能会很困难变通。
在我的 app.py
模块中,我设置了一个带有控制台和文件处理程序的记录器,如下所示:
import logging
logger = logging.getLogger('app')
logger.setLevel(logging.DEBUG)
console_handler = logging.StreamHandler()
file_handler = logging.FileHandler('gsam_log.txt')
console_handler.setLevel(logging.INFO)
file_handler.setLevel(logging.INFO)
c_formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
f_formatter = logging.Formatter('%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
console_handler.setFormatter(c_formatter)
file_handler.setFormatter(f_formatter)
logger.addHandler(console_handler)
logger.addHandler(file_handler)
如果我在 Python 控制台中工作并且我这样做:from app import logger
它按预期工作 - 打印到控制台和文件。我想使用这个记录器从我的 xlwings
潜艇(用 @xw.sub
装饰)记录。但出于某种原因,日志只发送到控制台而不是文件。下面是来自 test.py
模块的代码,我通过 xlwings.
from app import logger
import xlwings as xw
@xw.sub
def test():
logger.debug('test')
logger.info('test')
logger.warning('test')
我不太熟悉 xlwings
的工作原理,但由于 logging
模块的工作原理错综复杂,我建议不要在模块的全局范围内创建记录器,而是根据需要懒惰地创建它们。
在许多情况下,在全局范围内创建的日志是在之前创建的,任何代码都是运行。然后,其他一些代码会重新配置日志记录,这会导致删除现有日志并忘记其配置。这就是 disable_existing_loggers=False
参数存在于 logging.config
函数(例如 https://docs.python.org/2/library/logging.config.html#logging.config.fileConfig)的原因。
要查看是否是这种情况,我建议将您的日志定义代码移动到一个函数中,并根据需要调用它,例如:
导入日志记录
# app.py
_logger = None
def get_logger():
global _logger
if _logger is None:
_logger = logging.getLogger('app')
_logger.setLevel(logging.DEBUG)
# ... continue to define your logger ...
return _logger
然后在你的函数中:
from app import get_logger
import xlwings as xw
@xw.sub
def test():
logger = get_logger()
logger.debug('test')
logger.info('test')
logger.warning('test')
需要注意的是,这不是使用日志记录的 "cleanest" 方式(通常这不是必需的)但是如果问题真的是其他一些模块扰乱了日志记录配置,这可能会很困难变通。