var*_*ble 1 python python-3.x python-logging
我正在使用日志记录并有一个问题。
我知道有简单和高级的日志概念。
在简单日志中,我们有logging.info()等,而在高级日志中,我们有logging.getlogger(some_name).
在简单日志记录中,我们可以使用配置日志路径和消息格式,logging.
basicConfig而在高级日志记录的情况下,我们有格式化程序的概念,处理程序分配给通过使用获得的记录器logging.getlogger(some_name).addhandlers..
我们甚至可以使用以下方法向根记录器添加多个处理程序 logging.getlogger().addhandlers....
因此,高级日志记录的唯一好处是我们可以将记录器名称添加到硬编码值或__name__相应的模块值中。
那么既然格式化程序和处理程序都可以用于简单和高级日志记录方法,那么简单意味着根记录器和高级意味着模块名称记录器吗?
basicConfig 只能用于根记录器,而处理程序/格式化器只能用于命名记录器吗?
忠告
首先,简单和复杂(或基本和高级)是相对的术语。您可以只使用具有非常复杂的日志记录配置的根记录器,您会称其为简单记录,因为您使用的是根记录器吗?不。您不应该将基本和高级等相关术语的语义(含义)与 Python 对象联系起来。语言结构的语义要么由它们引发的计算表示,要么由它们产生的效果表示,这对每个人来说都是一样的。
词典
其次,让我们澄清几个术语。
logging是一个 Python module。
basicConfig&getLogger是模块级函数。
debug(),info(),warning()等都是这两个模块级函数和类方法,这取决于你怎么称呼他们。如果你这样做,logging.debug(msg)你正在调用一个模块级函数,如果你这样做,some_logger.debug(msg)你正在调用一个方法。模块级函数本身也在幕后调用根方法。
执行流程和层次结构
在root当您导入伐木机械,即当你这样做会自动创建记录import logging-在root记录器会自动创建,这反过来,让你做简单的调用,例如logging.debug(),它使用的是根记录。
基本上,模块级函数如下所示:
def debug(msg, *args, **kwargs):
"""
Log a message with severity 'DEBUG' on the root logger. If the logger has
no handlers, call basicConfig() to add a console handler with a pre-defined
format.
"""
if len(root.handlers) == 0:
basicConfig()
root.debug(msg, *args, **kwargs)
Run Code Online (Sandbox Code Playgroud)
记录器按层次结构组织,所有记录器都是记录器的后代root。
当您调用getLogger(name)ifname存在时,它将返回 that logger,如果不存在,它将创建 that logger。该getLogger(name)函数是幂等的,这意味着对于具有相同名称的后续调用,无论您调用多少次,它都只会返回现有的记录器。
该名称可能是一个以句点分隔的分层值,例如foo.bar.baz. 在层次列表中更靠后的记录器是列表中更高的记录器的孩子。例如,给定一个记录器使用的名称foo,记录仪用的名字foo.bar,foo.bar.baz以及foo.bam是所有后代foo。
创建记录器时,级别设置为NOTSET(当记录器是非根记录器时,这会导致将所有消息委托给父级)。这意味着如果记录器的级别为 NOTSET,则遍历其祖先记录器链,直到找到具有 NOTSET 级别以外的祖先或到达根。
没有深入细节,这里是相关链接:记录器对象、模块级函数、执行流程。
你的问题
在简单日志中,我们可以使用日志来配置日志路径和消息格式。basicConfig 而在高级日志记录的情况下,我们有格式化程序的概念,处理程序分配给使用 logging.getlogger(some_name).addhandlers 获得的记录器。
不。
basicConfig,正如我们现在所知,是一个模块级函数。这个函数建立基本配置为你的测井系统,应该先天下之忧叫,因为如果你做任何记录的调用是自己以前一样的功能debug(),info()等会叫basicConfig()自动,如果没有处理程序的根记录定义. 这个函数也是幂等的,这意味着一旦你调用它一次,你可以调用它十亿次而没有任何影响。但是此调用将决定您的日志记录将如何用于所有记录器,而不仅仅是根记录器(因为所有记录器都通过层次结构连接)并将消息从一个传递到另一个,除非您为后代记录器指定显式配置。
路径是您希望记录日志消息的位置,这是通过处理程序设置的,它可以是控制台、文件、电子邮件等等……请在此处查看完整列表。
格式是您希望消息显示的方式,您希望它们包含什么样的信息,这是通过formatters完成的,您可以在其中提供所需的日志记录属性。这些属性决定了日志记录知道哪些信息。
但这一切都可以协同工作。Handlers附属于loggers并且formatters附属于handlers。您可以通过basicConfig或dictConfig或fileConfig为整个应用程序设置一次,也可以根据logger.
因此,高级日志记录的唯一好处是我们可以将记录器名称添加到硬编码值或作为相应模块值的名称中。
不。
更复杂的日志记录意味着您可以将应用程序拆分为多个模块并loggers为每个模块单独设置,并拥有一个非常精细的消息系统,其中应用程序的每个部分记录不同的内容(您希望敏感部分记录非常具体的信息,也许通过电子邮件快速发送它们或将它们记录到文件中),而您希望将琐碎的部分轻轻记录下来并通过控制台打印它们。
basicConfig 只能用于根记录器,而处理程序/格式化器只能用于命名记录器吗?
basicConfig将设置root记录器的配置,所有记录器都将使用该配置,除非另有说明。
例子
import logging
root = logging.getLogger()
print(root.handlers) # no handlers at this point
logging.warning('hello') # calls basicConfig
print(root.handlers) # has handler now
# create file handler
fh = logging.FileHandler('spam.log')
fh.setLevel(logging.ERROR)
# create formatter and add it to the handlers
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter)
# add the handlers to the logger
root.addHandler(fh)
print(root.handlers) # now has 2 handlers
root.warning('whats good') # will only show to console
root.error('whats good') # will show to console and file
random_logger = logging.getLogger('bogus') # another logger, descendant from root
random_logger.warning('im random') # will use root handlers, meaning it will show to console
random_logger.error('im random error') # same as above, both console and file
# and you can ofc add handlers and what not differently to this non root logger
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1370 次 |
| 最近记录: |