basicConfig只能在根记录器上使用,而处理程序/格式化程序只能在命名记录器上使用吗? [英] Can basicConfig only be used on root logger and handlers/formatter only be used on namedloggers?

查看:82
本文介绍了basicConfig只能在根记录器上使用,而处理程序/格式化程序只能在命名记录器上使用吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用日志记录,并且有一个问题.

I am working with logging and have a question.

我知道有简单和高级的日志记录概念.

I know there are simple and advanced logging concepts.

在简单日志记录中,我们有logging.info()等,而在高级日志记录中,我们有logging.getlogger(some_name).

In simple logging, we have the logging.info(), etc whereas in advanced logging we have logging.getlogger(some_name).

在简单日志记录中,我们可以使用logging. basicConfig配置日志路径和msg格式,而在高级日志记录的情况下,我们具有格式化程序的概念,即通过logging.getlogger(some_name).addhandlers..

In simple logging, we can configure the log path and msg format using logging. basicConfig whereas in case of advanced logging we have the concept of a formatter, handler which is assigned to the logger obtained by using logging.getlogger(some_name).addhandlers..

我们甚至可以使用logging.getlogger().addhandlers....

因此,高级日志记录的唯一好处是我们可以将记录器名称添加到硬编码值或__name__(分别是模块值)中.

So the only benefit of advanced logging is the possibility for us to add the logger name either to a hardcoded value or to __name__ which is respective module value.

因此,既然格式化程序和处理程序可在简单和高级日志记录方法中使用,那么简单均值根记录器和高级均值模块名称记录器是否可用?

So since formatter and handler can be used in both simple and advanced logging approaches, does simple mean root logger and advanced mean module name logger?

basicConfig仅可用于根记录器,而处理程序/格式化程序仅可用于命名记录器?

Can basicConfig only be used on root logger and handlers/formatter only be used on namedloggers?

推荐答案

建议词

首先,简单和复杂(或基本和高级)是相对术语.您可能只有具有非常复杂的日志记录配置的root记录器,因为您使用的是root记录器,您将之称为简单记录吗?不.您不应该将诸如基本和高级之类的相对术语的语义(含义)与Python对象联系在一起.语言结构的语义通过它们引起的计算或它们产生的效果来表示,这对于每个人来说都是相同的.

Firstly, simple and complex (or basic and advanced) are relative terms. You could have just the root logger with a very complex logging configuration, would you call that simple logging, because you're using the root logger ? No. You shouldn't tie the semantics (meaning) of relative terms like basic and advanced to Python objects. The semantics of language constructs is denoted either by the computation they induce or by the effect they produce, which is always the same for everybody.

词典

第二,让我们澄清一些术语.

Secondly, let's clear up a few terms.

  • logging是Python module.

basicConfig& getLogger是模块级功能.

basicConfig & getLogger are module level functions.

debug()info()warning()等都是模块级功能和类方法,具体取决于您如何调用它们.如果您执行logging.debug(msg),则在调用模块级函数,如果您执行some_logger.debug(msg),则在调用方法.模块级别的函数本身也会在后台调用root方法.

debug(), info(), warning(), etc. are both module level functions and class methods, depending on how you call them. If you do logging.debug(msg) you're calling a module level function, if you do some_logger.debug(msg) you're calling a method. The module level function itself also calls the root method under the hood.

执行流程层次结构

root记录器是在导入日志记录机器时自动创建的,即,当您执行import logging时-root记录器是自动创建的,从而使您可以进行直接调用,例如logging.debug() ,它使用那个根记录器.

The root logger is automatically created when you import the logging machinery, i.e when you do import logging - the root logger is automatically created which, in turn, enables you to do straightforward calls such as logging.debug(), which use that root logger.

基本上,模块级功能如下:

Basically, a module level function looks like this:

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)

记录器是按层次结构组织的,所有记录器都是root记录器的后代.

Loggers are organized in hierarchies, and all loggers are descendants of the root logger.

如果name存在,则对getLogger(name)进行调用时,它将返回该logger,如果不存在,它将创建该logger. getLogger(name)函数是幂等,这意味着,对于以后使用相同名称的调用,无论您调用它多少次,它都将仅返回该现有记录器.

When you do a call to getLogger(name) if the name exists it will return that logger, if it doesn't, it will create that logger. The getLogger(name) function is idempotent, meaning, for subsequent calls with the same name it will just return that existing logger no matter how many times you call it.

该名称可能是句点分隔的分层值,例如foo.bar.baz.层次结构列表中位于最下方的记录器是列表中较高位置的记录器的子级.例如,给定名称为foo的记录器,名称为foo.barfoo.bar.bazfoo.bam的记录器都是foo的后代.

The name is potentially a period-separated hierarchical value, like foo.bar.baz. Loggers that are further down in the hierarchical list are children of loggers higher up in the list. For example, given a logger with a name of foo, loggers with names of foo.bar, foo.bar.baz, and foo.bam are all descendants of foo.

创建记录器时,级别设置为 NOTSET (当记录器为非root记录器时,这会将所有消息委派给父级).这意味着,如果记录器的级别为NOTSET,则遍历其祖先记录器链,直到找到非NOTSET级别的祖先或到达根为止.

When a logger is created, the level is set to NOTSET (which causes all messages to be delegated to the parent when the logger is a non-root logger). This means that if a logger has a level of NOTSET, its chain of ancestor loggers is traversed until either an ancestor with a level other than NOTSET is found, or the root is reached.

这里没有详细介绍,以下是相关链接:记录器对象模块级函数执行流程.

Without going very deep in the details, here are the relevant links: logger objects, module level functions, flow of execution.

您的问题

在简单的日志记录中,我们可以使用以下命令配置日志路径和msg格式 记录. basicConfig,而在进行高级日志记录的情况下, 格式化程序的概念,分配给记录器的处理程序 通过使用logging.getlogger(some_name).addhandlers ..

In simple logging, we can configure the log path and msg format using logging. basicConfig whereas in case of advanced logging we have the concept of a formatter, handler which is assigned to the logger obtained by using logging.getlogger(some_name).addhandlers..

否.

basicConfig 是一个模块级功能.此函数为您的日志记录系统设置了基本配置,应该在其他任何东西之前调用,因为如果在调用自己之前进行任何类型的日志记录,则debug()info()等函数会自动调用basicConfig()如果没有为根记录器定义处理程序.此功能也是幂等的,这意味着一旦调用一次,便可以调用十亿次,而没有任何效果.但是此调用将确定您的日志记录如何用于所有记录器,而不仅仅是根(因为所有记录器都通过层次结构连接),并将消息从一个传递到另一个,除非您为后代记录器指定显式配置.

basicConfig, as we now know, is a module level function. This function sets up the basic configuration for your logging system and should be called before anything else, because if you do any kind of logging before calling that yourself, functions like debug(), info(), etc. will call basicConfig() automatically if no handlers are defined for the root logger. This function is also idempotent, meaning once you call it once, you can call it a billion times after with no effect. But this call will determine how your logging will work for all loggers not just the root (because all loggers are connected through hierarchies) and pass messages from one to another, unless you specify explicit configuration for descendant loggers.

路径是您希望记录日志消息的位置,该路径是通过

The path is where you want your log messages to be recorded, and this is set up via handlers and it can be the console, a file, an email, whatever... see a complete list here.

格式是您希望消息显示的方式,希望包含的信息类型,并且可以通过

The format is how you want your messages to show, what kind of information you want them to contain, and that is done via formatters, where you provide the log record attributes you want. Those attributes determine which information a logrecord knows about.

但这可以一起使用. Handlers附加到loggers,并且formatters附加到handlers.您可以通过 basicConfig 或 dictConfig fileConfig ,或者您可以根据.

But this all works together. Handlers are attached to loggers and formatters are attached to handlers. You can set these up one time per your entire application via basicConfig or dictConfig or fileConfig or you can set these up individually, per logger.

因此,高级日志记录的唯一好处是我们可以 将记录器名称添加到硬编码值或名称 是各自的模块值.

So the only benefit of advanced logging is the possibility for us to add the logger name either to a hardcoded value or to name which is respective module value.

否.

更复杂的日志记录意味着您可以将应用程序划分为模块,每个模块具有单独的loggers,并且具有非常完善的消息系统,其中应用程序的每个部分都记录不同的内容(您希望敏感部分记录非常具体的信息,并可能通过电子邮件将其快速发送或将它们记录到文件中),而您希望琐碎的部分可以轻松记录并仅通过控制台进行打印.

More complex logging means that you can split your application into modules and have separate loggers for each module, and have a very refined message system, where each part of the application logs different things (you'd want sensitive parts to log very specific information and maybe send them rapidly via email or log them to a file) whereas you'd want trivial parts to log lightly and just print them via console.

basicConfig仅可用于根记录器和处理程序/格式化程序 仅用于命名记录器?

Can basicConfig only be used on root logger and handlers/formatter only be used on namedloggers?

basicConfig将设置root记录器的配置,除非另外指定,否则所有记录器将依次使用.

basicConfig will set the configuration for the root logger which in turn all loggers will use, unless otherwise specified.

示例

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

这篇关于basicConfig只能在根记录器上使用,而处理程序/格式化程序只能在命名记录器上使用吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆