>  기사  >  백엔드 개발  >  Python에서 로그를 구성하는 여러 가지 방법

Python에서 로그를 구성하는 여러 가지 방법

不言
不言원래의
2018-04-18 14:22:521287검색

이 글에서는 Python의 구성 로그를 자세히 설명하는 여러 가지 방법을 주로 소개하고 참고용으로 제공합니다. 함께 살펴보겠습니다

개발자로서 우리는 다음 3가지 방법으로 로깅을 구성할 수 있습니다.

1) Python 코드를 사용하여 명시적으로 로거, 핸들러 및 포맷터를 생성하고 해당 구성 함수를 각각 호출합니다.

2) 구성 파일을 기록한 다음 fileConfig() 함수를 사용하여 파일 내용을 읽습니다.

3) 구성 정보가 포함된 dict를 만든 다음 이를 dictConfig() 함수에 전달합니다. 예, logging.basicConfig()도 첫 번째 메소드에 속하며 로거, 핸들러 및 포맷터의 구성 기능을 캡슐화합니다. 또한 첫 번째 구성 방법에 비해 두 번째 구성 방법의 장점은 구성 정보와 코드를 분리하여 로그 유지 관리 비용을 줄이고 개발자가 아닌 사람도 쉽게 로그 구성을 수정할 수 있다는 점입니다.

1. Python 코드를 사용하여 로그 구성 구현logging.basicConfig()也属于第一种方式,它只是对loggers, handlers和formatters的配置函数进行了封装。另外,第二种配置方式相对于第一种配置方式的优点在于,它将配置信息和代码进行了分离,这一方面降低了日志的维护成本,同时还使得非开发人员也能够去很容易地修改日志配置。

一、使用Python代码实现日志配置

代码如下:

# 创建一个日志器logger并设置其日志级别为DEBUG
logger = logging.getLogger('simple_logger')
logger.setLevel(logging.DEBUG)

# 创建一个流处理器handler并设置其日志级别为DEBUG
handler = logging.StreamHandler(sys.stdout)
handler.setLevel(logging.DEBUG)

# 创建一个格式器formatter并将其添加到处理器handler
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
handler.setFormatter(formatter)

# 为日志器logger添加上面创建的处理器handler
logger.addHandler(handler)

# 日志输出
logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')

运行输出:

2017-05-15 11:30:50,955 - simple_logger - DEBUG - debug message
2017-05-15 11:30:50,955 - simple_logger - INFO - info message
2017-05-15 11:30:50,955 - simple_logger - WARNING - warn message
2017-05-15 11:30:50,955 - simple_logger - ERROR - error message
2017-05-15 11:30:50,955 - simple_logger - CRITICAL - critical message

二、使用配置文件和fileConfig()函数实现日志配置

现在我们通过配置文件的方式来实现与上面同样的功能:

# 读取日志配置文件内容
logging.config.fileConfig('logging.conf')

# 创建一个日志器logger
logger = logging.getLogger('simpleExample')

# 日志输出
logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')

配置文件logging.conf内容如下:

[loggers]
keys=root,simpleExample

[handlers]
keys=fileHandler,consoleHandler

[formatters]
keys=simpleFormatter

[logger_root]
level=DEBUG
handlers=fileHandler

[logger_simpleExample]
level=DEBUG
handlers=consoleHandler
qualname=simpleExample
propagate=0

[handler_consoleHandler]
class=StreamHandler
args=(sys.stdout,)
level=DEBUG
formatter=simpleFormatter

[handler_fileHandler]
class=FileHandler
args=('logging.log', 'a')
level=ERROR
formatter=simpleFormatter

[formatter_simpleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
datefmt=

运行输出:

2017-05-15 11:32:16,539 - simpleExample - DEBUG - debug message
2017-05-15 11:32:16,555 - simpleExample - INFO - info message
2017-05-15 11:32:16,555 - simpleExample - WARNING - warn message
2017-05-15 11:32:16,555 - simpleExample - ERROR - error message
2017-05-15 11:32:16,555 - simpleExample - CRITICAL - critical message

1. 关于fileConfig()函数的说明:

该函数实际上是对configparser模块的封装,关于configparser模块的介绍请参考<。

函数定义:

该函数定义在loging.config模块下:


复制代码 代码如下:


logging.config.fileConfig(fname, defaults=None, disable_existing_loggers=True)

参数:

  1. fname:表示配置文件的文件名或文件对象

  2. defaults:指定传给ConfigParser的默认值

  3. disable_existing_loggers:这是一个布尔型值,默认值为True(为了向后兼容)表示禁用已经存在的logger,除非它们或者它们的祖先明确的出现在日志配置中;如果值为False则对已存在的loggers保持启动状态。

2. 配置文件格式说明:

上面提到过,fileConfig()函数是对ConfigParser/configparser模块的封装,也就是说fileConfig()函数是基于ConfigParser/configparser模块来理解日志配置文件的。换句话说,fileConfig()函数所能理解的配置文件基础格式是与ConfigParser/configparser模块一致的,只是在此基础上对文件中包含的sectionoption

코드는 다음과 같습니다.

[logger_simpleExample]
level=DEBUG
handlers=consoleHandler
qualname=simpleExample
propagate=1

실행 출력:

🎜

# 读取日志配置文件内容
logging.config.fileConfig(&#39;logging.conf&#39;)

# 创建一个日志器logger
logger = logging.getLogger(&#39;simpleExample&#39;)

# 日志输出
logger.debug(&#39;debug message&#39;)
logger.info(&#39;info message&#39;)
logger.warn(&#39;warn message&#39;)
logger.error(&#39;error message&#39;)
logger.critical(&#39;critical message&#39;)
🎜🎜🎜2. 구성 파일과 fileConfig() 함수를 사용하여 로그 구성 구현🎜🎜이제 구성 파일을 사용하여 위와 동일한 기능을 구현합니다. 🎜🎜

🎜

2017-05-15 16:06:25,366 - simpleExample - ERROR - error message
2017-05-15 16:06:25,367 - simpleExample - CRITICAL - critical message
🎜🎜🎜구성 파일logging.conf의 내용은 다음과 같습니다. 🎜🎜

🎜

# 读取日志配置文件内容
logging.config.fileConfig(&#39;logging.conf&#39;)

# 用一个没有在配置文件中定义的logger名称来创建一个日志器logger
logger = logging.getLogger(&#39;simpleExample1&#39;)

# 日志输出
logger.debug(&#39;debug message&#39;)
logger.info(&#39;info message&#39;)
logger.warn(&#39;warn message&#39;)
logger.error(&#39;error message&#39;)
logger.critical(&#39;critical message&#39;)
🎜🎜🎜실행 출력: 🎜🎜

🎜

2017-05-15 16:13:16,810 - simpleExample1 - ERROR - error message
2017-05-15 16:13:16,810 - simpleExample1 - CRITICAL - critical message
🎜🎜🎜1. fileConfig() 함수 설명:🎜🎜 이 함수는 실제로 configparser 모듈을 캡슐화한 것입니다. >configparser 모듈에 대해서는 < ;를 참조하세요. 🎜🎜함수 정의: 🎜🎜이 함수는logging.config 모듈 아래에 정의됩니다: 🎜🎜🎜🎜🎜

코드 복사 코드는 다음과 같습니다.🎜

🎜logging.config.fileConfig(fname, defaults=None, 비활성화_existing_loggers=True)🎜🎜🎜매개변수: 🎜

  1. 🎜 fname: 구성 파일의 파일 이름 또는 파일 객체를 나타냅니다🎜
  2. 🎜defaults: ConfigParser🎜에 전달되는 기본값을 지정합니다.
  3. 🎜disable_existing_loggers: 부울 값입니다. 기본값은 True(이전 버전과의 호환성을 위해)입니다. 기존 로거 또는 해당 조상이 로깅 구성에 명시적으로 나타나지 않는 한 기존 로거를 비활성화합니다. False 값은 기존 로거를 활성화합니다. 🎜
🎜2. 구성 파일 형식 설명: 🎜🎜위에서 언급했듯이 fileConfig() 함수는 ConfigParser에 대한 참조입니다. /configparser 모듈 캡슐화, 즉 fileConfig() 함수는 로그 구성 파일을 이해하기 위해 ConfigParser/configparser 모듈을 기반으로 합니다. 즉, fileConfig() 함수가 이해할 수 있는 구성 파일의 기본 형식은 ConfigParser/configparser 모듈과 일치하지만, 이를 기준으로 >파일에 포함된 내용이 수정되었습니다. code>섹션옵션에는 다음과 같은 몇 가지 규정 및 제한 사항이 있습니다. 🎜🎜1) 구성 파일에는 로거, 핸들러 및 구성 파일에 정의된 로거, 핸들러 및 포맷터는 쉼표로 구분되며 로거 섹션의 키에는 루트 값이 포함되어야 합니다. ​​로거, 핸들러 및 포맷터에 지정됨 로거, 프로세서 및 포맷터는 모두 아래의 별도 섹션에서 정의되어야 합니다. seciton의 명명 규칙은 [logger_loggerName], [formatter_formatterName], [handler_handlerName]🎜🎜3) 로거를 정의하는 섹션에서는 level 및 handlers의 두 가지 옵션을 지정해야 합니다. level의 가능한 값은 DEBUG, INFO입니다. , WARNING, ERROR, CRITICAL, NOTSET. 여기서 NOTSET은 사용자 정의 수준을 포함하여 모든 수준의 로그 메시지가 기록되어야 함을 나타냅니다. 핸들러 값은 쉼표로 구분된 핸들러 이름 목록입니다. [handlers] 섹션과 해당 핸들러는 구성 파일에 해당 섹션 정의가 있어야 합니다. 🎜🎜4) 루트가 아닌 로거의 경우 레벨 및 핸들러의 두 가지 옵션 외에도 몇 가지 추가 옵션이 필요합니다. qualname은 제공되어야 하는 옵션입니다. 이는 로거 수준의 이름이 애플리케이션 코드에서 이 이름을 통해 획득됨을 의미하며 기본값은 1입니다. 이는 메시지가 전달됨을 의미합니다. 일반적으로 해당 값을 0으로 지정해야 합니다. 또한 아래 예를 살펴보세요. 루트가 아닌 로거의 수준이 NOTSET으로 설정된 경우 시스템은 이 로거의 유효 수준을 결정하려면 더 높은 수준의 로거를 찾으십시오. 🎜

5)定义handler的section中必须指定class和args这两个option,level和formatter为可选option;class表示用于创建handler的类名,args表示传递给class所指定的handler类初始化方法参数,它必须是一个元组(tuple)的形式,即便只有一个参数值也需要是一个元组的形式;level与logger中的level一样,而formatter指定的是该处理器所使用的格式器,这里指定的格式器名称必须出现在formatters这个section中,且在配置文件中必须要有这个formatter的section定义;如果不指定formatter则该handler将会以消息本身作为日志消息进行记录,而不添加额外的时间、日志器名称等信息;

6)定义formatter的sectioin中的option都是可选的,其中包括format用于指定格式字符串,默认为消息字符串本身;datefmt用于指定asctime的时间格式,默认为'%Y-%m-%d %H:%M:%S';class用于指定格式器类名,默认为logging.Formatter;

说明:

配置文件中的class指定类名时,该类名可以是相对于logging模块的相对值,如:FileHandlerhandlers.TimeRotatingFileHandler;也可以是一个绝对路径值,通过普通的import机制来解析,如自定义的handler类mypackage.mymodule.MyHandler,但是mypackage需要在Python可用的导入路径中--sys.path。

3. 对于propagate属性的说明

实例1:

我们把logging.conf中simpleExample这个handler定义中的propagate属性值改为1,或者删除这个option(默认值就是1):

[logger_simpleExample]
level=DEBUG
handlers=consoleHandler
qualname=simpleExample
propagate=1

现在来执行同样的代码:

# 读取日志配置文件内容
logging.config.fileConfig(&#39;logging.conf&#39;)

# 创建一个日志器logger
logger = logging.getLogger(&#39;simpleExample&#39;)

# 日志输出
logger.debug(&#39;debug message&#39;)
logger.info(&#39;info message&#39;)
logger.warn(&#39;warn message&#39;)
logger.error(&#39;error message&#39;)
logger.critical(&#39;critical message&#39;)

我们会发现,除了在控制台有输出信息时候,在logging.log文件中也有内容输出:

2017-05-15 16:06:25,366 - simpleExample - ERROR - error message
2017-05-15 16:06:25,367 - simpleExample - CRITICAL - critical message

这说明simpleExample这个logger在处理完日志记录后,把日志记录传递给了上级的root logger再次做处理,所有才会有两个地方都有日志记录的输出。通常,我们都需要显示的指定propagate的值为0,防止日志记录向上层logger传递。

实例2:

现在,我们试着用一个没有在配置文件中定义的logger名称来获取logger:

# 读取日志配置文件内容
logging.config.fileConfig(&#39;logging.conf&#39;)

# 用一个没有在配置文件中定义的logger名称来创建一个日志器logger
logger = logging.getLogger(&#39;simpleExample1&#39;)

# 日志输出
logger.debug(&#39;debug message&#39;)
logger.info(&#39;info message&#39;)
logger.warn(&#39;warn message&#39;)
logger.error(&#39;error message&#39;)
logger.critical(&#39;critical message&#39;)

运行程序后,我们会发现控制台没有任何输出,而logging.log文件中又多了两行输出:

2017-05-15 16:13:16,810 - simpleExample1 - ERROR - error message
2017-05-15 16:13:16,810 - simpleExample1 - CRITICAL - critical message

这是因为,当一个日志器没有被设置任何处理器是,系统会去查找该日志器的上层日志器上所设置的日志处理器来处理日志记录。simpleExample1在配置文件中没有被定义,因此logging.getLogger(simpleExample1)这行代码这是获取了一个logger实例,并没有给它设置任何处理器,但是它的上级日志器--root logger在配置文件中有定义且设置了一个FileHandler处理器,simpleExample1处理器最终通过这个FileHandler处理器将日志记录输出到logging.log文件中了。

三、使用字典配置信息和dictConfig()函数实现日志配置

Python 3.2中引入的一种新的配置日志记录的方法--用字典来保存logging配置信息。这相对于上面所讲的基于配置文件来保存logging配置信息的方式来说,功能更加强大,也更加灵活,因为我们可把很多的数据转换成字典。比如,我们可以使用JSON格式的配置文件、YAML格式的配置文件,然后将它们填充到一个配置字典中;或者,我们也可以用Python代码构建这个配置字典,或者通过socket接收pickled序列化后的配置信息。总之,你可以使用你的应用程序可以操作的任何方法来构建这个配置字典。

这个例子中,我们将使用YAML格式来完成与上面同样的日志配置。

首先需要安装PyYAML模块:

pip install PyYAML

Python代码:

import logging
import logging.config
import yaml

with open(&#39;logging.yml&#39;, &#39;r&#39;) as f_conf:
  dict_conf = yaml.load(f_conf)
logging.config.dictConfig(dict_conf)

logger = logging.getLogger(&#39;simpleExample&#39;)
logger.debug(&#39;debug message&#39;)
logger.info(&#39;info message&#39;)
logger.warn(&#39;warn message&#39;)
logger.error(&#39;error message&#39;)
logger.critical(&#39;critical message&#39;)

logging.yml配置文件的内容:
version: 1
formatters:
 simple:
  format: &#39;%(asctime)s - %(name)s - %(levelname)s - %(message)s&#39;
handlers:
 console:
  class: logging.StreamHandler
  level: DEBUG
  formatter: simple
  stream: ext://sys.stdout
 console_err:
  class: logging.StreamHandler
  level: ERROR
  formatter: simple
  stream: ext://sys.stderr
loggers:
 simpleExample:
  level: DEBUG
  handlers: [console]
  propagate: yes
root:
 level: DEBUG
 handlers: [console_err]

输出结果:

2017-05-21 14:19:31,089 - simpleExample - DEBUG - debug message
2017-05-21 14:19:31,089 - simpleExample - INFO - info message
2017-05-21 14:19:31,089 - simpleExample - WARNING - warn message
2017-05-21 14:19:31,089 - simpleExample - ERROR - error message
2017-05-21 14:19:31,090 - simpleExample - CRITICAL - critical message

1. 关于dictConfig()函数的说明:

该函数实际上是对configparser模块的封装。

函数定义:

该函数定义在loging.config模块下:

logging.config.dictConfig(config)

该函数可以从一个字典对象中获取日志配置信息,config参数就是这个字典对象。关于这个字典对象的内容规则会在下面进行描述。

2. 配置字典说明

无论是上面提到的配置文件,还是这里的配置字典,它们都要描述出日志配置所需要创建的各种对象以及这些对象之间的关联关系。比如,可以先创建一个名额为“simple”的格式器formatter;然后创建一个名为“console”的处理器handler,并指定该handler输出日志所使用的格式器为"simple";然后再创建一个日志器logger,并指定它所使用的处理器为"console"。

传递给dictConfig()函数的字典对象只能包含下面这些keys,其中version是必须指定的key,其它key都是可选项:


key名称 描述
version 必选项,其值是一个整数值,表示配置格式的版本,当前唯一可用的值就是1
formatters 可选项,其值是一个字典对象,该字典对象每个元素的key为要定义的格式器名称,value为格式器的配置信息组成的dict,如format和datefmt
filters 可选项,其值是一个字典对象,该字典对象每个元素的key为要定义的过滤器名称,value为过滤器的配置信息组成的dict,如name
handlers 可选项,其值是一个字典对象,该字典对象每个元素的key为要定义的处理器名称,value为处理器的配置信息组成的dcit,如class、level、formatter和filters,其中class为必选项,其它为可选项;其他配置信息将会传递给class所指定的处理器类的构造函数,如下面的handlers定义示例中的stream、filename、maxBytes和backupCount等
loggers 可选项,其值是一个字典对象,该字典对象每个元素的key为要定义的日志器名称,value为日志器的配置信息组成的dcit,如level、handlers、filters 和 propagate(yes
root 可选项,这是root logger的配置信息,其值也是一个字典对象。除非在定义其它logger时明确指定propagate值为no,否则root logger定义的handlers都会被作用到其它logger上
incremental 可选项,默认值为False。该选项的意义在于,如果这里定义的对象已经存在,那么这里对这些对象的定义是否应用到已存在的对象上。值为False表示,已存在的对象将会被重新定义。
disable_existing_loggers 可选项,默认值为True。该选项用于指定是否禁用已存在的日志器loggers,如果incremental的值为True则该选项将会被忽略

handlers定义示例:

handlers:
 console:
  class : logging.StreamHandler
  formatter: brief
  level  : INFO
  filters: [allow_foo]
  stream : ext://sys.stdout
 file:
  class : logging.handlers.RotatingFileHandler
  formatter: precise
  filename: logconfig.log
  maxBytes: 1024
  backupCount: 3

3. 关于外部对象的访问

需要说明的是,上面所使用的对象并不限于loggging模块所提供的对象,我们可以实现自己的formatter或handler类。另外,这些类的参数也许需要包含sys.stderr这样的外部对象。如果配置字典对象是使用Python代码构造的,可以直接使用sys.stdout、sys.stderr;但是当通过文本文件(如JSON、YAML格式的配置文件)提供配置时就会出现问题,因为在文本文件中,没有标准的方法来区分sys.stderr和字符串 'sys.stderr'。为了区分它们,配置系统会在字符串值中查找特定的前缀,例如'ext://sys.stderr'中'ext://'会被移除,然后import sys.stderr



위 내용은 Python에서 로그를 구성하는 여러 가지 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.