我希望能够使用Python日志工具在我的代码中进行简单一致的日志记录。
我可以执行以下操作:
don't want to add everywhere
所示)。log.info(...)
等构造在我在项目层次结构中定义的任何函数中都有效。什么不起作用/我不知道该怎么做:
@log
装饰器。# don't want to add everywhere
FORMAT = '%(asctime)s - %(name)-20s - %(levelname)-5s - %(message)s'
LEVEL = logging.DEBUG
logging.basicConfig(format=FORMAT, level=LEVEL)
log = logging.getLogger(__name__)
我的Flask项目的示例代码:
# app/__init__.py
from a import b # various other imports required for app
import logging
FORMAT = '%(asctime)s - %(name)-20s - %(levelname)-5s - %(message)s'
LEVEL = logging.DEBUG
logging.basicConfig(format=FORMAT, level=LEVEL)
log = logging.getLogger(__name__)
# ... various other app init code
from app import views, models
#app/views.py
from c import d # various other imports required for the module
def logger(fn):
from functools import wraps
import inspect
@wraps(fn)
def wrapper(*args, **kwargs):
global log
log = logging.getLogger(inspect.stack()[1][3])
log.info('About to run %s' % fn.__name__)
out = apply(fn, args, kwargs)
log.info('Done running %s' % fn.__name__)
# Return the return value
return out
return wrapper
@app.route('/this_func')
@logger
def this_func():
log.info('I am doing logging without having to do bunch of definitions.')
# some more code
@app.route('/that_func')
@logger
def that_func():
log.info('Yet more logging without having to do bunch of definitions.')
log.info('I can simply refer to the log object and be done with it.')
# some more code
答案 0 :(得分:7)
对我有用的最终设置如下:
# At the beginning of every .py file in the project
def logger(fn):
from functools import wraps
import inspect
@wraps(fn)
def wrapper(*args, **kwargs):
log = logging.getLogger(fn.__name__)
log.info('About to run %s' % fn.__name__)
out = apply(fn, args, kwargs)
log.info('Done running %s' % fn.__name__)
# Return the return value
return out
return wrapper
# Do the following section only in application's app/__init__.py
# Other files will pick it up from here.
FORMAT = '%(asctime)s - %(name)s - %(levelname)s - %(funcName)s - %(message)s'
# Change logging LEVEL according to debugging needs.
# Probably better to read this from a config or a launch parameter.
LEVEL = logging.DEBUG
logging.basicConfig(format=FORMAT, level=LEVEL)
# Up to here only for app/__init__.py
# This section again at the beginning of every .py file
log = logging.getLogger(__name__)
log.info('Entered module: %s' % __name__)
现在,为模块中的每个函数定义添加一个@logger
装饰器:
@logger
def do_something():
print('doing really useful stuff.')
答案 1 :(得分:1)
将contextlib与异常处理一起使用。
import logging
from time import time
logging.basicConfig(level=logging.INFO, format='%(asctime)s | %(levelname)s | %(processName)s | %(thread)d | %(message)s')
log = logging.getLogger(__name__)
@contextmanager
def EEL(methodDescr, raiseExcp=False):
'''EEL = Entry Exit Log'''
log.info(f"Starting function: {methodDescr}")
start = time()
try:
yield
except Exception as ex:
log.exception("Got exception")
finally:
end = time()
log.info(f"Time taken by {methodDescr}: {end-start}")
用法:
@EEL("Test method")
def test():
x = 0
for i in range(1,1000000):
x = x + i
输出:
2020-09-22 11:09:17,418 | INFO | MainProcess | 139709531875200 | Starting function: Test method
2020-09-22 11:09:17,484 | INFO | MainProcess | 139709531875200 | Time taken by Test method: 0.06573295593261719