cwo*_*ker 49 python logging module global-variables
我想知道如何实现一个可以在任何地方使用您自己的设置的全局记录器:
我目前有一个自定义记录器类:
class customLogger(logging.Logger):
...
Run Code Online (Sandbox Code Playgroud)
该类位于一个单独的文件中,包含一些格式化程序和其他内容.记录仪可以完美地完成.
我在我的主python文件中导入这个模块并创建一个这样的对象:
self.log = logModule.customLogger(arguments)
Run Code Online (Sandbox Code Playgroud)
但显然,我无法从代码的其他部分访问此对象.我使用了错误的方法吗?有一个更好的方法吗?
小智 108
使用logging.getLogger(name)创建一个名为全球记录.
main.py
import log
logger = log.setup_custom_logger('root')
logger.debug('main message')
import submodule
Run Code Online (Sandbox Code Playgroud)
log.py
import logging
def setup_custom_logger(name):
formatter = logging.Formatter(fmt='%(asctime)s - %(levelname)s - %(module)s - %(message)s')
handler = logging.StreamHandler()
handler.setFormatter(formatter)
logger = logging.getLogger(name)
logger.setLevel(logging.DEBUG)
logger.addHandler(handler)
return logger
Run Code Online (Sandbox Code Playgroud)
submodule.py
import logging
logger = logging.getLogger('root')
logger.debug('submodule message')
Run Code Online (Sandbox Code Playgroud)
产量
2011-10-01 20:08:40,049 - DEBUG - main - main message
2011-10-01 20:08:40,050 - DEBUG - submodule - submodule message
Run Code Online (Sandbox Code Playgroud)
Den*_*nis 45
由于我没有找到满意的答案,我想详细阐述一下这个问题的答案,以便对loggingPython的标准库附带的库的工作和意图有所了解.
与OP(原始海报)的方法相反,库清楚地将接口与记录器和记录器本身的配置分开.
处理程序的配置是使用您的库的应用程序开发人员的特权.
这意味着你应该不是创建一个自定义logger类,并通过添加任何配置或任何配置类中的记录.
该logging库引入了四个组件:记录器,处理程序,过滤器和格式化程序.
- 记录器公开应用程序代码直接使用的接口.
- 处理程序将日志记录(由记录器创建)发送到适当的目标.
- 过滤器提供了更精细的设施,用于确定要输出的日志记录.
- Formatters指定最终输出中日志记录的布局.
一个常见的项目结构如下所示:
Project/
|-- .../
| |-- ...
|
|-- project/
| |-- package/
| | |-- __init__.py
| | |-- module.py
| |
| |-- __init__.py
| |-- project.py
|
|-- ...
|-- ...
Run Code Online (Sandbox Code Playgroud)
在代码中(比如在module.py中),您可以引用模块的记录器实例来记录特定级别的事件.
命名记录器时使用的一个好习惯是在每个使用日志记录的模块中使用模块级记录器,命名如下:
logger = logging.getLogger(__name__)
Run Code Online (Sandbox Code Playgroud)
特殊变量__name__是指模块的名称,看起来类似于project.package.module应用程序的代码结构.
module.py(和任何其他类)基本上看起来像这样:
import logging
...
log = logging.getLogger(__name__)
class ModuleClass:
def do_something(self):
log.debug('do_something() has been called!')
Run Code Online (Sandbox Code Playgroud)
每个模块中的记录器会将任何事件传播到父记录器,然后父记录器将信息传递给其附加的处理程序!类似于python包/模块结构,父记录器由名称空间使用"点模块名称"确定.这就是为什么用特殊__name__变量初始化记录器是有意义的(在上面的例子中,名称匹配字符串"project.package.module").
全局配置记录器有两个选项:
在project.py中实例化一个记录器,其名称在本例中__package__等于"project",因此是所有子模块记录器的父记录器.只需要在此记录器中添加适当的处理程序和格式化程序.
在执行脚本(如main.py)中使用处理程序和格式化程序设置一个记录器,其名称为最顶层的程序包.
在开发使用日志记录的库时,您应该注意记录库如何使用日志记录 - 例如,使用的记录器的名称.
执行脚本,例如main.py,最终可能看起来像这样:
import logging
from project import App
def setup_logger():
# create logger
logger = logging.getLogger('project')
logger.setLevel(logging.DEBUG)
# create console handler and set level to debug
ch = logging.StreamHandler()
ch.setLevel(level)
# create formatter
formatter = logging.Formatter('%(asctime)s [%(levelname)s] %(name)s: %(message)s')
# add formatter to ch
ch.setFormatter(formatter)
# add ch to logger
logger.addHandler(ch)
if __name__ == '__main__' and __package__ is None:
setup_logger()
app = App()
app.do_some_funny_stuff()
Run Code Online (Sandbox Code Playgroud)
方法调用log.setLevel(...)指定记录器将处理但不一定输出的最低严重性日志消息!它只是意味着只要消息的严重性级别高于(或等于)设置的消息,消息就会传递给处理程序.但是处理程序负责处理日志消息(例如通过打印或存储它).
因此,logging图书馆提供了一种结构化和模块化的方法,只需要根据需要进行开发.
Fun*_* LI 13
python 日志记录模块作为全局记录器已经足够好了,您可能只是寻找这个:
主要.py
import logging
logging.basicConfig(level = logging.DEBUG,format = '[%(asctime)s] %(levelname)s [%(name)s:%(lineno)s] %(message)s')
Run Code Online (Sandbox Code Playgroud)
将上面的代码放入您的执行脚本中,然后您可以在项目中的任何位置使用具有相同配置的记录器:
模块.py
import logging
logger = logging.getLogger(__name__)
logger.info('hello world!')
Run Code Online (Sandbox Code Playgroud)
对于更复杂的配置,您可以使用带有日志记录的配置文件logging.conf
logging.config.fileConfig("logging.conf")
Run Code Online (Sandbox Code Playgroud)