在阅读Python代码时,我经常会看到这两个约定之一:
def something(logger):
logger.info('doing something')
或:
LOGGER = logging.getLogger(__NAME__)
def something():
LOGGER.info('doing something')
前者是否有任何优点,即线程安全,而另一个不是?或者它纯粹是一种风格差异?
答案 0 :(得分:1)
如果要使用固定的记录器,请使用全局记录器:
LOGGER = logging.getLogger('stuff.do')
# logger depends on what we are
def do_stuff(operation: Callable):
LOGGER.info('will do stuff')
operation()
LOGGER.info('just did stuff')
do_stuff(add_things)
do_stuff(query_things)
通常在记录共享操作以进行诊断时使用。例如,Web服务器将记录创建和销毁线程的日志。
如果要更改记录器,请使用记录器参数:
# logger depends on what we do
def do_stuff(operation: Callable, logger: Logger):
logger.info('will do stuff')
operation()
logger.info('just did stuff')
do_stuff(add_things, logging.getLogger('add'))
do_stuff(query_things, logging.getLogger('query'))
通常在出于会计目的记录可配置操作时使用。例如,Web服务器将记录不同种类的请求及其结果。
使用哪种记录器完全取决于记录器的选择取决于全局还是本地数据。
如果可以全局决定记录器的选择,则这样做可以避免因记录器传递而污染功能签名。这样可以提高模块化,因为您可以添加/删除logging
调用而无需更改其他代码。使用日志记录查找错误时,您可能希望将日志记录添加到可疑的代码节,并将其从经过验证的代码节中删除。
如果记录器的选择取决于本地状态,则传递记录器或其名称通常是唯一的选择。使用日志记录正在发生的事情时,您有时有时希望稍后再添加新的操作主题。
使用任何一种方法都没有运行时或安全性优势,除了避免操作将事情四处传递。 logging
模块被设计为线程安全的:
日志模块旨在实现线程安全,而无需 客户需要完成的任何特殊工作。它实现了 尽管使用了线程锁;有一个锁可以序列化对 模块的共享数据,并且每个处理程序还会创建一个锁 序列化对其底层I / O的访问。
完全等同于为同一记录器创建一个新的“实例”,或为同一记录器创建一个别名:
>>> a = logging.getLogger('demo')
>>> b = a
>>> c = logging.getLogger('demo')
>>> a is b is c
True