程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Python logstore logging summary

編輯:Python

When deploying a project , It's impossible to output all the information directly to the console , We can record this information in a log file , This is not only convenient for us to check the running situation of the program , You can also quickly locate the problem location according to the log generated by the runtime when the project fails .

1、 The level of logging

Python Standard library logging Used as a log , There are six log levels by default ( Parentheses are the values corresponding to the level ),NOTSET(0)、DEBUG(10)、INFO(20)、WARNING(30)、ERROR(40)、CRITICAL(50). When we customize the log level, be careful not to have the same value as the default log level ,logging During execution, log information greater than or equal to the set log level is output , If the log level is set to INFO, be INFO、WARNING、ERROR、CRITICAL All level logs will be output .

2、logging technological process

Official logging The work flow chart of the module is as follows :

From the figure below, we can see these Python type ,LoggerLogRecordFilterHandlerFormatter.

Type specification :

Logger: journal , Expose functions to applications , Determine which logs are valid based on the logger and filter levels .

LogRecord : Loggers , Send the log to the corresponding processor for processing .

Handler : processor , take ( The loggers produce ) Log records are sent to the appropriate destination .

Filter : filter , Provides better granularity control , It can decide which logging to output .

Formatter: formatter , Indicates the layout of the logging in the final output .

  1. Judge Logger Object is available for the set level , If available , I'm going to go ahead and execute , otherwise , End of the process .
  2. establish LogRecord object , If you register to Logger Object Filter After object filtering, it returns False, The log is not recorded , End of the process , otherwise , Then go down .
  3. LogRecord Object will Handler Object passes in the current Logger object ,( The subprocess in the figure ) If Handler The log level of the object is greater than the set log level , Then judge to register to Handler Object Filter Whether to return... After object filtering True And release output log information , Otherwise, it will not be released , End of the process .
  4. If the incoming Handler Greater than Logger The level set in , That is to say Handler It works , I'm going to go ahead and execute , otherwise , End of the process .
  5. Judge this Logger Whether the object has a parent Logger object , without ( On behalf of the current Logger The object is at the top Logger object root Logger), End of the process . Otherwise it would be Logger Object as its parent Logger object , Repeat the above 3、4 Two steps , Output parent class Logger Object , Until it was root Logger until .

3、 Log output format

The output format of the log can be considered as setting , The default format is shown below .

4、 Basic use

logging Very simple to use , Use basicConfig() Method can meet the basic use needs , If the method does not pass in parameters , Will be created according to the default configuration Logger object , The default log level is set to WARNING, The default log output format is shown in the figure above , The optional parameters of this function are shown in the following table .

Parameter name

Parameters to describe

filename

The file name of the log output to the file

filemode

File mode ,r[+]、w[+]、a[+]

format

The format of the log output

datefat

Format of date and time attached to the log

style

Format placeholder , The default is "%" and “{}”

level

Set the log output level

stream

Define the output stream , Used to initialize StreamHandler object , You can't filename Parameters used together , Otherwise ValueError abnormal

handles

Define processor , Used to create Handler object , Unable to join filename 、stream Parameters used together , Otherwise, it will throw ValueError abnormal

The sample code is as follows :

import logging
logging.basicConfig()
logging.debug('This is a debug message')
logging.info('This is an info message')
logging.warning('This is a warning message')
logging.error('This is an error message')
logging.critical('This is a critical message')
Copy code 

The output is as follows :

WARNING:root:This is a warning message
ERROR:root:This is an error message
CRITICAL:root:This is a critical message
Copy code 

Pass in commonly used parameters , The sample code is as follows ( Here, the variables in the log format placeholder will be described later ):

import logging
logging.basicConfig(filename="test.log", filemode="w", format="%(asctime)s %(name)s:%(levelname)s:%(message)s", datefmt="%d-%m-%Y %H:%M:%S", level=logging.DEBUG)
logging.debug('This is a debug message')
logging.info('This is an info message')
logging.warning('This is a warning message')
logging.error('This is an error message')
logging.critical('This is a critical message')
Copy code 

Generated log files test.log , The contents are as follows :

13-10-18 21:10:32 root:DEBUG:This is a debug message
13-10-18 21:10:32 root:INFO:This is an info message
13-10-18 21:10:32 root:WARNING:This is a warning message
13-10-18 21:10:32 root:ERROR:This is an error message
13-10-18 21:10:32 root:CRITICAL:This is a critical message
Copy code 

But when an exception occurs , Use parameterless directly debug()、info()、warning()、error()、critical() Method does not record exception information , Need to set up exc_info Parameter is True Can only be , Or use exception() Method , You can also use log() Method , But also set the log level and exc_info Parameters .

import logging
logging.basicConfig(filename="test.log", filemode="w", format="%(asctime)s %(name)s:%(levelname)s:%(message)s", datefmt="%d-%M-%Y %H:%M:%S", level=logging.DEBUG)
a = 5
b = 0
try:
c = a / b
except Exception as e:
# Choose one of the following three ways , The first one is recommended
logging.exception("Exception occurred")
logging.error("Exception occurred", exc_info=True)
logging.log(level=logging.DEBUG, msg="Exception occurred", exc_info=True)
Copy code 

5、 Customize Logger

The above basic use can let us get started quickly logging modular , But generally, it can not meet the actual use , We also need to customize Logger.

A system has only one Logger object , And the object cannot be instantiated directly , you 're right , The singleton pattern is used here , obtain Logger The method of the object is getLogger.

Be careful : The singleton pattern here does not mean that there is only one Logger object , It means that the whole system has only one root Logger object ,Logger Object is executing info()、error() When a method is called, it is actually the root Logger The object corresponds to info()、error() Other methods .

We can create multiple Logger object , But the real output log is the root Logger object . Every Logger Objects can have a name , If you set logger = logging.getLogger(__name__),__name__ yes Python A special built-in variable in , It represents the name of the current module ( The default is __main__). be Logger Object's name It is recommended to use a namespace hierarchy with a dot as a separator .

Logger Object can be set to more than one Handler Objects and Filter object ,Handler Object can be set Formatter object .Formatter Object is used to set the specific output format , The format of common variables is shown in the following table , See... For all parameters Python(3.7) Official documents :

Variable

Format

Variable description

asctime

%(asctime)s

Construct the time of the log into a readable form , By default, it is accurate to milliseconds , Such as 2018-10-13 23:24:57,832, You can specify additional datefmt Parameter to specify the format of the variable

name

%(name)

The name of the log object

filename

%(filename)s

File name without path

pathname

%(pathname)s

The file name containing the path

funcName

%(funcName)s

The name of the function where the log is located

levelname

%(levelname)s

Level name of the log

message

%(message)s

Specific log information

lineno

%(lineno)d

The line number of the log record

pathname

%(pathname)s

The full path

process

%(process)d

The current process ID

processName

%(processName)s

Current process name

thread

%(thread)d

Current thread ID

threadName

%threadName)s

Current thread name

Logger Objects and Handler Objects can be set to a level , And default Logger The object level is 30 , That is to say WARNING, Default Handler The object level is 0, That is to say NOTSET.logging The module is designed for better flexibility , For example, sometimes we both want to output DEBUG Level of logging , I also want to output in the file WARNING Level of logging . You can set only the lowest level Logger object , Two different levels of Handler object , The sample code is as follows :

import logging
import logging.handlers
logger = logging.getLogger("logger")
handler1 = logging.StreamHandler()
handler2 = logging.FileHandler(filename="test.log")
logger.setLevel(logging.DEBUG)
handler1.setLevel(logging.WARNING)
handler2.setLevel(logging.DEBUG)
formatter = logging.Formatter("%(asctime)s %(name)s %(levelname)s %(message)s")
handler1.setFormatter(formatter)
handler2.setFormatter(formatter)
logger.addHandler(handler1)
logger.addHandler(handler2)
# Respectively 10、30、30
# print(handler1.level)
# print(handler2.level)
# print(logger.level)
logger.debug('This is a customer debug message')
logger.info('This is an customer info message')
logger.warning('This is a customer warning message')
logger.error('This is an customer error message')
logger.critical('This is a customer critical message')
Copy code 

The console output is :

2018-10-13 23:24:57,832 logger WARNING This is a customer warning message
2018-10-13 23:24:57,832 logger ERROR This is an customer error message
2018-10-13 23:24:57,832 logger CRITICAL This is a customer critical message
Copy code 

The output content in the file is :

2018-10-13 23:44:59,817 logger DEBUG This is a customer debug message
2018-10-13 23:44:59,817 logger INFO This is an customer info message
2018-10-13 23:44:59,817 logger WARNING This is a customer warning message
2018-10-13 23:44:59,817 logger ERROR This is an customer error message
2018-10-13 23:44:59,817 logger CRITICAL This is a customer critical message
Copy code 

Created a custom Logger object , Don't use it logging The log output method in , These methods are configured by default Logger object , Otherwise, the output log information will be repeated .

import logging
import logging.handlers
logger = logging.getLogger("logger")
handler = logging.StreamHandler()
handler.setLevel(logging.DEBUG)
formatter = logging.Formatter("%(asctime)s %(name)s %(levelname)s %(message)s")
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.debug('This is a customer debug message')
logging.info('This is an customer info message')
logger.warning('This is a customer warning message')
logger.error('This is an customer error message')
logger.critical('This is a customer critical message')
Copy code 

The output is as follows ( You can see that the log information is output twice ):

2018-10-13 22:21:35,873 logger WARNING This is a customer warning message
WARNING:logger:This is a customer warning message
2018-10-13 22:21:35,873 logger ERROR This is an customer error message
ERROR:logger:This is an customer error message
2018-10-13 22:21:35,873 logger CRITICAL This is a customer critical message
CRITICAL:logger:This is a customer critical message
Copy code 

explain : In the introduction of log output python When you file , Such as import test.py, After meeting the log level greater than the current setting, the log in the import file will be output .

6、Logger To configure

Through the example above , We know how to create a Logger The required configuration of the object , The above is directly hard coded to configure objects in the program , Configuration can also be obtained from dictionary type objects and configuration files . open logging.config Python file , You can see the configuration resolution conversion function .

Get configuration information from the dictionary :

import logging.config
config = {
'version': 1,
'formatters': {
'simple': {
'format': '%(asctime)s - %(name)s - %(levelname)s - %(message)s',
},
# Other formatter
},
'handlers': {
'console': {
'class': 'logging.StreamHandler',
'level': 'DEBUG',
'formatter': 'simple'
},
'file': {
'class': 'logging.FileHandler',
'filename': 'logging.log',
'level': 'DEBUG',
'formatter': 'simple'
},
# Other handler
},
'loggers':{
'StreamLogger': {
'handlers': ['console'],
'level': 'DEBUG',
},
'FileLogger': {
# both console Handler, also file Handler
'handlers': ['console', 'file'],
'level': 'DEBUG',
},
# Other Logger
}
}
logging.config.dictConfig(config)
StreamLogger = logging.getLogger("StreamLogger")
FileLogger = logging.getLogger("FileLogger")
# Omit log output
Copy code 

Get configuration information from the configuration file :

Common configuration files are ini Format 、yaml Format 、JSON Format , Or get it from the network , As long as there is a corresponding file parser parsing configuration , The following shows only ini Format and yaml Format configuration .

test.ini file

[loggers]
keys=root,sampleLogger
[handlers]
keys=consoleHandler
[formatters]
keys=sampleFormatter
[logger_root]
level=DEBUG
handlers=consoleHandler
[logger_sampleLogger]
level=DEBUG
handlers=consoleHandler
qualname=sampleLogger
propagate=0
[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=sampleFormatter
args=(sys.stdout,)
[formatter_sampleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
Copy code 

testinit.py file

import logging.config
logging.config.fileConfig(fname='test.ini', disable_existing_loggers=False)
logger = logging.getLogger("sampleLogger")
# Omit log output
Copy code 

test.yaml file

version: 1
formatters:
simple:
format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
handlers:
console:
class: logging.StreamHandler
level: DEBUG
formatter: simple
loggers:
simpleExample:
level: DEBUG
handlers: [console]
propagate: no
root:
level: DEBUG
handlers: [console]
Copy code 

testyaml.py file

import logging.config
# Need to install pyymal library
import yaml
with open('test.yaml', 'r') as f:
config = yaml.safe_load(f.read())
logging.config.dictConfig(config)
logger = logging.getLogger("sampleLogger")
# Omit log output
Copy code 

7、 Problems in actual combat

1、 Chinese garbled

In the above example, the log output is in English , If you can't output the log to the file, there will be Chinese garbled code , How to solve this problem ?FileHandler When creating an object, you can set the file code , If the file encoding is set to “utf-8”(utf-8 and utf8 Equivalent ), You can solve the problem of Chinese garbled code . One way is to customize Logger object , You need to write a lot of configuration , Another method is to use the default configuration method basicConfig(), Pass in handlers Processor list object , Among them handler Set the encoding of the file . Many online methods are ineffective , The key reference codes are as follows :

# Customize Logger To configure
handler = logging.FileHandler(filename="test.log", encoding="utf-8")
Copy code 
# Use default Logger To configure
logging.basicConfig(handlers=[logging.FileHandler("test.log", encoding="utf-8")], level=logging.DEBUG)
Copy code 

2、 Temporarily disable log output

Sometimes we don't want log output , But after that, I want to output the log . If we print information with print() Method , Then you need to put all print() Methods are commented out , And used logging after , We have a one button switch to close the log " magic ". One way is to use the default configuration , to logging.disabled() Method to pass in the disabled log level , You can disable log output below the setting level , Another way is to customize Logger when ,Logger Object's disable Property set to True, The default value is False, That is, do not disable .

logging.disable(logging.INFO)
Copy code 
logger.disabled = True
Copy code 

3、 Log files are divided by time or size

If you save the log in a file , For a long time , Or more logs , A single log file will be large , It is not conducive to backup , And it's not good to see . We wonder if we can divide the log files according to time or size ? The answer must be yes , And it's simple ,logging Considering our needs .logging.handlers Provided in the document TimedRotatingFileHandler and RotatingFileHandler Class can be divided according to time and size . Open this. handles file , You can see that there are other functions Handler class , They all inherit from the base class BaseRotatingHandler.

# TimedRotatingFileHandler Class constructor
def __init__(self, filename, when='h', interval=1, backupCount=0, encoding=None, delay=False, utc=False, atTime=None):
# RotatingFileHandler Class constructor
def __init__(self, filename, mode='a', maxBytes=0, backupCount=0, encoding=None, delay=False)
Copy code 

The sample code is as follows :

# every other 1000 Byte Divide a log file , Backup file is 3 individual
file_handler = logging.handlers.RotatingFileHandler("test.log", mode="w", maxBytes=1000, backupCount=3, encoding="utf-8")
Copy code 
# every other 1 Hours Divide a log file ,interval It's the time interval , Backup file is 10 individual
handler2 = logging.handlers.TimedRotatingFileHandler("test.log", when="H", interval=1, backupCount=10)
Copy code 

Python Although the official website says logging Libraries are thread safe , But in multiple processes 、 Multithreading 、 There are still problems worth considering in a multi process and multi-threaded environment , such as , How to log by process ( Or thread ) Divided into different log files , That is, a process ( Or thread ) Corresponding to a file .

summary :Python logging The library design is really flexible , If you have special needs, you can also use this foundation logging Improve on the library , Create a new Handler Class to solve problems in practical development .


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved