如何在Python中的函数入口,内部和出口处进行日志记录 [英] How to do logging at function entry, inside and exit in Python

查看:260
本文介绍了如何在Python中的函数入口,内部和出口处进行日志记录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望能够使用Python日志记录工具在我的代码中进行简单且一致的日志记录.

I'd like to be able to do simple and consistent logging in my code using the Python logging facility.

我能够执行以下操作:

  1. 我希望所有现有/将来的模块和功能都具有"Entering ..."和"Done ..."日志消息.
  2. 我不想在每个函数定义中为定义日志记录参数(显示在don't want to add everywhere下)添加相同的代码段.
  3. 我希望log.info(...) etc构造可以在我在项目层次结构中定义的任何功能中使用.
  1. I'd like all existing/future module and functions to have "Entering ..." and "Done ..." log messages.
  2. I don't want to add the same code snippet to defining logging parameters (shown below don't want to add everywhere) in every function definition.
  3. I want the log.info(...) etc constructs to work in any function I define in the project hierarchy.

什么是行不通的/我不知道该怎么做:

  1. 我想避免在我编写的每个现有/新模块中定义相同的@log装饰器.
  1. I'd like to avoid defining the same @log decorator in every existing/new module that I write.

# 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

推荐答案

对我有用的最终设置如下:

The final setup that worked for me was the following:

# 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装饰器:

Now, add a @logger decorator to every function definition in the module:

@logger
def do_something():
    print('doing really useful stuff.')

这篇关于如何在Python中的函数入口,内部和出口处进行日志记录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆