logger应该是参数还是全局变量?

d33*_*tah 6 python logging conventions

在阅读Python代码时,我通常会看到以下两种约定之一:

def something(logger):
  logger.info('doing something')
Run Code Online (Sandbox Code Playgroud)

要么:

LOGGER = logging.getLogger(__NAME__)
def something():
  LOGGER.info('doing something')
Run Code Online (Sandbox Code Playgroud)

前者有什么优势,即线程安全,而另一种则没有?还是纯粹是风格上的差异?

Mis*_*agi 5

如果您想要固定记录器,请使用全局记录器:

\n\n
LOGGER = logging.getLogger(\'stuff.do\')\n\n# logger depends on what we are\ndef do_stuff(operation: Callable):\n    LOGGER.info(\'will do stuff\')\n    operation()\n    LOGGER.info(\'just did stuff\')\n\ndo_stuff(add_things)\ndo_stuff(query_things)\n
Run Code Online (Sandbox Code Playgroud)\n\n

这通常在出于诊断目的记录共享操作时使用。例如,Web 服务器会记录线程的创建和销毁。

\n\n

如果要更改记录器,请使用记录器参数:

\n\n
# logger depends on what we do\ndef do_stuff(operation: Callable, logger: Logger):\n    logger.info(\'will do stuff\')\n    operation()\n    logger.info(\'just did stuff\')\n\ndo_stuff(add_things, logging.getLogger(\'add\'))\ndo_stuff(query_things, logging.getLogger(\'query\'))\n
Run Code Online (Sandbox Code Playgroud)\n\n

这通常在出于记账目的记录可配置操作时使用。例如,网络服务器会记录不同类型的请求及其结果。

\n\n
\n\n

使用哪一种完全取决于记录器的选择是否取决于全局数据或本地数据。

\n\n

如果可以全局决定记录器选择,则可以避免记录器传递污染函数签名。这提高了模块化性,因为您可以添加/删除logging调用而无需更改其他代码。当使用日志记录来查找错误时,您可能希望将日志记录添加到可疑的代码部分,并将其从经过验证的代码部分中删除。

\n\n

如果记录器的选择取决于当地状态,则传递记录器或其名称通常是唯一的选择。当使用日志记录来记录正在发生的事情时,您有时希望稍后添加新类型的操作主题。

\n\n
\n\n

除了避免传递事物的操作之外,使用这两种方法都没有运行时或安全优势。该logging模块被设计为线程安全的:

\n\n
\n

线程安全

\n\n

日志记录模块旨在是线程安全的,\n 客户端不需要执行任何特殊工作。它通过使用线程锁来实现这一点;有一个锁用于序列化对模块 xe2\x80\x99 共享数据的访问,并且每个处理程序还创建一个锁来序列化对其底层 I/O 的访问。

\n
\n\n

它完全相当于创建同一记录器的新“实例”,或者为同一记录器创建别名:

\n\n
>>> a = logging.getLogger(\'demo\')\n>>> b = a\n>>> c = logging.getLogger(\'demo\')\n>>> a is b is c\nTrue\n
Run Code Online (Sandbox Code Playgroud)\n