python logging 模組 使用總結
阿新 • • 發佈:2019-01-10
logging python 中的日誌模組
最近嘗試使用了python中的日誌庫 logging, 作簡單使用總結
有什麼問題或建議請留言告知 , 感謝閱讀
簡單理解就是 logger 相當於申明瞭一個外殼
Handler 類似於 logger 的一套規則,來填充 logger ,並告訴 logger 怎麼以哪種方式輸出日誌
自己常用的 handler : StreamHandler, fileHandler
Python 提供了其它的 handler,參考 logging.handlers
Formatter 則表示日誌輸出格式及內容,以下列一些常用的:
%(levelno)s: 列印日誌級別的數值
%(levelname)s: 列印日誌級別名稱
%(pathname)s: 列印當前執行程式的路徑,其實就是sys.argv[0]
%(filename)s: 列印當前執行程式名
%(funcName)s: 列印日誌的當前函式
%(lineno)d: 列印日誌的當前行號
%(asctime)s: 列印日誌的時間
%(thread)d: 列印執行緒ID
%(threadName)s: 列印執行緒名稱
%(process)d: 列印程序ID
%(message)s: 列印日誌資訊
嘗試了log的三種配置方式:
1. basicConfig 配置方式
conf_format = ' [ %(asctime)-15s ] - %(name)s - %(levelname)s - %(pathname)s[line : %(lineno)d] - FUNNAME : [%(funcName)s] - MESSAGE : %(message)s '
def log_test_first():
'''
first method 單個日誌檔案,同時列印控制檯
'''
try:
print(sys.stdout.__dict__)
console = logging.StreamHandler(sys.stdout) ##StreamHandler 能夠將日誌資訊輸出到sys.stdout, sys.stderr 或者類檔案物件
console.setLevel(logging.INFO)
formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
console.setFormatter(formatter)
##
## basicConfig方法 傳入filename會自動構造一個filehandler 傳入stream則會自動構造一個StreamHandler
## 但二者不可同時傳入 同時傳入預設使用filename引數 stream會被忽略
logging.basicConfig(
level=logging.INFO,
format=conf_format,
datefmt='%Y/%m/%d %H:%M:%S',
filename=f"./{os.path.split(__file__)[-1].split('.')[0]}.log",
filemode='w' )
logging.getLogger('').addHandler(console)
logger = logging.getLogger('First method')
logger.info('Log_test_first_test-AAAAAAAAAAAAAAAA')
except Exception :
traceback.print_exc()
def log_test_second():
'''
second method 多個日誌檔案,同時列印控制檯, 同一個formatter 並且udp推日誌到 syslog 服務處理
SysLogHandler
'''
try:
syslog = logging.handlers.SysLogHandler(address=("0.0.0.0", 514), socktype=socket.SOCK_DGRAM)
syslog.setFormatter(
logging.Formatter('%(asctime)s,%(msecs)03d [%(levelname)s] [%(name)s] %(funcName)s %(lineno)d: %(message)s')
)
logging.basicConfig(level=logging.DEBUG,
format=conf_format,
handlers=[logging.FileHandler("example1.log"),
syslog,
logging.FileHandler("example2.log"),
logging.StreamHandler()])
logging.getLogger(__name__)
logging.info('xxx')
except Exception as e:
traceback.print_exc()
2. logging.config.dictConfig 構造 json 配置方式 多個format 多個handler
def log_test_third():
LOGGING = {
'version': 1,
'disable_existing_loggers': True,
## 宣告2個format
'formatters': {
'simple': {'format': '%(levelname)s %(message)s'},
'default': { 'format' : '%(asctime)s %(message)s', 'datefmt' : '%Y-%m-%d %H:%M:%S'
}
},
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
'formatter': 'simple',
"stream": sys.stderr
},
'file': {
'level': 'INFO',
'class': 'logging.FileHandler',
'formatter': 'default',
'filename' : 'example3.log',
}
},
'loggers' : {
# 定義了一個logger
'mylogger' : {
'level' : 'DEBUG',
'handlers' : [ 'file'],
'propagate' : True
},
'mylogger_console' : {
'level' : 'DEBUG',
'handlers' : ['console'],
'propagate' : True
}
}
}
logging.config.dictConfig(LOGGING)
logger = logging.getLogger('mylogger_console')
logger.info('test')
3. logging.config.fileConfig() 配置檔案方式
## 配置檔案 log.conf :
[loggers] # logger 名稱
keys=root,mylogger
[handlers] # handlers 名稱
keys=console,file
[formatters]
keys=verbose,simple,default
[formatter_verbose]
format=%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s
datefmt=
class=logging.Formatter
[formatter_simple]
format=%(levelname)s %(message)s
datefmt=
class=logging.Formatter
[formatter_default]
format=%(asctime)s %(message)s
datefmt=%Y-%m-%d %H:%M:%S
class=logging.Formatter
[logger_mylogger]
level=DEBUG
handlers=console,file
propagate=1
qualname=lyj
[logger_root]
level=NOTSET
handlers=
[handler_console]
class=StreamHandler
level=DEBUG
args=()
[handler_file]
class=FileHandler
level=INFO
formatter=default
args=('file_version.log','a')
; [handler_file]
; class=handlers.TimedRotatingFileHandler
; level=INFO
; formatter=default
; args=('log','M',1,0,'utf8')
python程式碼:
def log_test_fourth():
logging.config.fileConfig('log.conf')
logger = logging.getLogger('lyj.root')
logger.info('xxxx')
個人覺得json配置方式最為可讀 。