在哪里配置日志记录?
Where to configure logging?
我想知道在哪里配置和初始化与日志模块相关的东西?
例如,我写了一些 class 并且我想在执行方法时记录一些信息。我应该在模块顶部的 init 或更高版本 class 中配置日志记录:
# LOGGING STUFF <--- Should be here ?
class SomeClass:
def __init__(self):
# class stuff
# LOGGING STUFF <--- Or should be here ?
def some_method(self):
# method stuff
# LOGGING SOME INFO
def some_method2(self):
# method stuff
# LOGGING SOME INFO
最佳做法是什么?
日志包有两个用途,协助作者生产日志和协助用户消费日志。您可能同时扮演这两个角色,但分别考虑它们将有助于您编写干净、易于理解的代码。
作者的担忧
作者应该在正确的级别实例化记录器:
包记录器应该放在包 __init__
文件中。注意 __name__
的使用,它会解析为 SomePackage
:
import logging
package_logger = logging.getLogger(__name__)
模块顶部的模块记录器。注意 __name__
的威力!在这里它将解析为 SomePackage.SomeModule
.
import logging
module_logger = logging.getLogger(__name__)
Class 级别记录器可以放在 class 定义的顶部。请注意 getLogger 和 __qualname__
增强的 __name__
的强大功能!记录器名称将为 SomePackage.SomeModule.SomeClass
。此外,不是 _class_logger
中的下划线表示它供内部使用。:
class SomeClass:
_class_logger = logging.getLogger(__name__).getChild(__qualname__)
classes __init__
中的实例记录器。使用 ID 生成唯一标识符。注意这个傻瓜……你明白了。记录器名称将为 SomePackage.SomeModule.SomeClass.<large_unique_number>
:
class SomeClass:
def __init__(self):
self._instance_logger = logging.getLogger(__name__).getChild(self.__class__.__name__).getChild(str(id(self)))
名称可能不适合您的应用。例如,您可能需要一个实例记录器,它派生自其中一个实例化参数。但是,您仍然应该以正确的水平掌握您的记录器。
用户关注
配置处理程序是用户的工作。通常,作者会确保默认情况下不会激活任何处理程序。 logging.basicConfig
会将warning及以上级别的所有日志记录转储到stderr。
import SomePackage
import logging
logging.basicConfig()
请记住,您可以使用 logging.getLogger() 访问作者定义的相同记录器。
from SomePackage import SomeModule
import logging
"""
module_logger debug to a file. Will capture all
child loggers as well if used i.e class_logger and
instance_logger
"""
h = logging.FileHandler('debug')
h.setLevel('DEBUG')
SomeModule.module_logger.addHandler(h)
"""
class_logger warning to stderr. Will capture all child loggers
as well if used i.e instance_logger Note: No need to import
SomeClass to access it's logger as Logger keeps track of them in
a dictionary. Typically the prefered approach if your not
actually using the class.
"""
h = logging.StreamHandler()
getLogger('SomePackage.SomeModule.SomeClass').addHandler(h)
如果您通过直接调用自己的模块来调试它们,您可能有一个 def main()
,它们应该放在那里。这确保包用户不会收到意外的日志文件或控制台消息。
加分
如果在多个级别使用记录器,从现有记录器派生更符合 pythonic。
module_logger = logging.getLogger(__name__)
class SomeClass:
_class_logger = module_logger.getChild(__qualname__)
def __init__(self):
self._instance_logger = self._class_logger.getChild(str(id(self)))
我想知道在哪里配置和初始化与日志模块相关的东西?
例如,我写了一些 class 并且我想在执行方法时记录一些信息。我应该在模块顶部的 init 或更高版本 class 中配置日志记录:
# LOGGING STUFF <--- Should be here ?
class SomeClass:
def __init__(self):
# class stuff
# LOGGING STUFF <--- Or should be here ?
def some_method(self):
# method stuff
# LOGGING SOME INFO
def some_method2(self):
# method stuff
# LOGGING SOME INFO
最佳做法是什么?
日志包有两个用途,协助作者生产日志和协助用户消费日志。您可能同时扮演这两个角色,但分别考虑它们将有助于您编写干净、易于理解的代码。
作者的担忧
作者应该在正确的级别实例化记录器:
包记录器应该放在包
__init__
文件中。注意__name__
的使用,它会解析为SomePackage
:import logging package_logger = logging.getLogger(__name__)
模块顶部的模块记录器。注意
__name__
的威力!在这里它将解析为SomePackage.SomeModule
.import logging module_logger = logging.getLogger(__name__)
Class 级别记录器可以放在 class 定义的顶部。请注意 getLogger 和
__qualname__
增强的__name__
的强大功能!记录器名称将为SomePackage.SomeModule.SomeClass
。此外,不是_class_logger
中的下划线表示它供内部使用。:class SomeClass: _class_logger = logging.getLogger(__name__).getChild(__qualname__)
classes
__init__
中的实例记录器。使用 ID 生成唯一标识符。注意这个傻瓜……你明白了。记录器名称将为SomePackage.SomeModule.SomeClass.<large_unique_number>
:class SomeClass: def __init__(self): self._instance_logger = logging.getLogger(__name__).getChild(self.__class__.__name__).getChild(str(id(self)))
名称可能不适合您的应用。例如,您可能需要一个实例记录器,它派生自其中一个实例化参数。但是,您仍然应该以正确的水平掌握您的记录器。
用户关注
配置处理程序是用户的工作。通常,作者会确保默认情况下不会激活任何处理程序。 logging.basicConfig
会将warning及以上级别的所有日志记录转储到stderr。
import SomePackage
import logging
logging.basicConfig()
请记住,您可以使用 logging.getLogger() 访问作者定义的相同记录器。
from SomePackage import SomeModule
import logging
"""
module_logger debug to a file. Will capture all
child loggers as well if used i.e class_logger and
instance_logger
"""
h = logging.FileHandler('debug')
h.setLevel('DEBUG')
SomeModule.module_logger.addHandler(h)
"""
class_logger warning to stderr. Will capture all child loggers
as well if used i.e instance_logger Note: No need to import
SomeClass to access it's logger as Logger keeps track of them in
a dictionary. Typically the prefered approach if your not
actually using the class.
"""
h = logging.StreamHandler()
getLogger('SomePackage.SomeModule.SomeClass').addHandler(h)
如果您通过直接调用自己的模块来调试它们,您可能有一个 def main()
,它们应该放在那里。这确保包用户不会收到意外的日志文件或控制台消息。
加分
如果在多个级别使用记录器,从现有记录器派生更符合 pythonic。
module_logger = logging.getLogger(__name__)
class SomeClass:
_class_logger = module_logger.getChild(__qualname__)
def __init__(self):
self._instance_logger = self._class_logger.getChild(str(id(self)))