【Python】#规范# 关于日志的那点事

it2022-05-06  9

==== 前言 == 自勉 =========

20160526 今天开了一个科室会议,感觉事情有点杂。。。期待数据库的迁移任务

当你可以给别人讲东西的时候,才是你真正学会的时候。

======================

import logging

======================

**** 小浪浪:之前的日志部分 ****

前一阵子,帮公司用一个PyQt写一个GUI,刚开始的时候,感觉内容很简单,所以关于编程规范方面的事情,就没太注意。写的很随意,想print就print。没有规范化的日志输出等格式。后来公司除了一个脚本规范文档,发觉让在脚本书写时,写日志。。。。

格式为[yyyy-mm-dd hh:mi:ss][WARNING] message

当时并不知道有logging这个模块,于是自己写这个模块。我觉得最重要的部分就是这个时间戳,所以当时的代码对于时间戳的处理如下:

1 import time 2 3 def log_write(level, message): 4 now_timestamp = time.strftime("%Y%m%d_%H%M%S",time.localtime()) 5 # 将当前时间格式化转换成想要的结构 6 7 result_line = "[%s][%s] %s" % (now_timestamp, level, message) 8 9 return result_line 10

虽然这么写了,也可以表达了日志的内容,但是如果需要将日志写入到文件中时,就会很麻烦。每次要open、close文件。

所以之前非常不喜欢写日志,想着等程序调整好再追加日志。但真实情况时,如果调整成功时,便不会再去添加日志,反正自己写的代码,哪里有问题一看就知道了。

非常坏的习惯!!!! 于是再次认真学习Python,蜕变成大浪浪。

**************************

----- 大浪浪:专业的日志 ---------

突然听别人介绍到一个logging模块,当看到它的使用时,震惊了~原来可以这么简单!

所以根据自己的python代码情况,做了一个关于【日志】的规范,要求自己以后再书写时,按照以下内容书写

-- 该规范要求logging既可以写入文档,又可以展示在屏幕。

#/usr/env/bin python #-*- coding=utf-8 -*- import logging # 关于日志的书写只要有四个步骤: # (1)Loggers: 创建 # (2)Handlers:把日志传送给合适的目标 # (3)Filters: 过滤出想要的内容 # (4)Formatters: 格式化 # 日志等级(从小到大): # debug()-->info()-->warning()-->error()-->critical() # Step 1: Loggers, 并设置全局level logger = logging.getLogger('logging_blog') logger.setLevel(logging.DEBUG) # Step 2: Handler # print to screen ch = logging.StreamHandler() ch.setLevel(logging.DEBUG) # write to file fh = logging.FileHandler('log_file.log') fh.setLevel(logging.WARNING) # Step 3: Formatter my_formatter = logging.Formatter('[%(asctime)s][%(name)s][%(levelname)s]%(message)s') ch.setFormatter(my_formatter) fh.setFormatter(my_formatter) logger.addHandler(ch) logger.addHandler(fh) # 开始使用:不同等级会写入到屏幕和文件中 logger.debug('This is a debug log.') logger.info('This is a info log.') logger.warning('This is a warning log.') logger.error('This is a error log.') logger.critical('This is a critial log.')

执行后屏幕的输出为:

[2016-05-26 21:49:50,825][logging_blog][DEBUG]This is a debug log. [2016-05-26 21:49:50,851][logging_blog][INFO]This is a info log. [2016-05-26 21:49:50,855][logging_blog][WARNING]This is a warning log. [2016-05-26 21:49:50,858][logging_blog][ERROR]This is a error log. [2016-05-26 21:49:50,865][logging_blog][CRITICAL]This is a critial log.

执行后文件的输出为:

[2016-05-26 21:49:50,855][logging_blog][WARNING]This is a warning log. [2016-05-26 21:49:50,858][logging_blog][ERROR]This is a error log. [2016-05-26 21:49:50,865][logging_blog][CRITICAL]This is a critial log.

----------------- 分割 ------------------------------

既然想这个模块,就要认真的写!!

【官方文档链接】https://docs.python.org/3.4/library/logging.html

1. 设置logging的基本配置:

1 import logging 2 3 logging.basicConfig(level=logging.DEBUG, 4 format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s', 5 datefmt='%Y%M%D %H:%M:%S', 6 filename='my.log', 7 filemode='w') 8 # 以上logging的设定,是用于对于写入文件的设定。

关于logging.basicConfig的参数:

filenameSpecifies that a FileHandler be created, using the specified filename, rather than a StreamHandler.filemodeSpecifies the mode to open the file, if filename is specified (if filemode is unspecified, it defaults to ‘a’).formatUse the specified format string for the handler.datefmtUse the specified date/time format.styleIf format is specified, use this style for the format string. One of ‘%’, ‘{‘ or ‘$’ for %-formatting, str.format() orstring.Template respectively, and defaulting to ‘%’ if not specified.levelSet the root logger level to the specified level.streamUse the specified stream to initialize the StreamHandler. Note that this argument is incompatible with ‘filename’ - if both are present, a ValueError is raised.handlersIf specified, this should be an iterable of already created handlers to add to the root logger. Any handlers which don’t already have a formatter set will be assigned the default formatter created in this function. Note that this argument is incompatible with ‘filename’ or ‘stream’ - if both are present, a ValueError is raised.

其中stream参数和filename参数不可以一起使用!!

关于format的格式化内容:

Attribute nameFormatDescriptionargsYou shouldn’t need to format this yourself.The tuple of arguments merged into msg to produce message, or a dict whose values are used for the merge (when there is only one argument, and it is a dictionary).asctime%(asctime)sHuman-readable time when the LogRecord was created. By default this is of the form ‘2003-07-08 16:49:45,896’ (the numbers after the comma are millisecond portion of the time).created%(created)fTime when the LogRecord was created (as returned by time.time()).exc_infoYou shouldn’t need to format this yourself.Exception tuple (à la sys.exc_info) or, if no exception has occurred, None.filename%(filename)sFilename portion of pathname.funcName%(funcName)sName of function containing the logging call.levelname%(levelname)sText logging level for the message ('DEBUG''INFO''WARNING''ERROR','CRITICAL').levelno%(levelno)sNumeric logging level for the message (DEBUGINFOWARNINGERROR,CRITICAL).lineno%(lineno)dSource line number where the logging call was issued (if available).module%(module)sModule (name portion of filename).msecs%(msecs)dMillisecond portion of the time when the LogRecord was created.message%(message)sThe logged message, computed as msg args. This is set whenFormatter.format() is invoked.msgYou shouldn’t need to format this yourself.The format string passed in the original logging call. Merged with args to produce message, or an arbitrary object (see Using arbitrary objects as messages).name%(name)sName of the logger used to log the call.pathname%(pathname)sFull pathname of the source file where the logging call was issued (if available).process%(process)dProcess ID (if available).processName%(processName)sProcess name (if available).relativeCreated%(relativeCreated)dTime in milliseconds when the LogRecord was created, relative to the time the logging module was loaded.stack_infoYou shouldn’t need to format this yourself.Stack frame information (where available) from the bottom of the stack in the current thread, up to and including the stack frame of the logging call which resulted in the creation of this record.thread%(thread)dThread ID (if available).threadName%(threadName)sThread name (if available).

也可以如下自定义使用format:但是这里的key必须是跟上面表格中不重复的!!!!

1 FORMAT = '%(asctime)-15s %(clientip)s %(user)-8s %(message)s' 2 logging.basicConfig(format=FORMAT) 3 d = {'clientip': '192.168.0.1', 'user': 'fbloggs'} 4 logger = logging.getLogger('tcpserver') 5 logger.warning('Protocol problem: %s', 'connection reset', extra=d)

2. 关于日志是否也存在文件关闭的问题:

(1)Handler

Handler.close()

Tidy up any resources used by the handler. This version does no output but removes the handler from an internal list of handlers which is closed whenshutdown() is called. Subclasses should ensure that this gets called from overridden close() methods.

(2)logging

logging.shutdown()

Informs the logging system to perform an orderly shutdown by flushing and closing all handlers. This should be called at application exit and no further use of the logging system should be made after this call.

 

 

---------------------------------

转载于:https://www.cnblogs.com/shuo-yang0459/p/5533139.html


最新回复(0)