如何让被调用函数与装饰器一起记录?

时间:2014-04-21 09:01:04

标签: python logging decorator python-decorators

我想写一些日志文件中的一些事件。为了做到这一点,我使用函数装饰器来添加loggin代码,并报告所调用的函数。但是,输出始终是相同的函数,即装饰器函数_decorador

我在格式logging.basicConfig中使用%(funcName)s参数

example.log中的输出:

04/21/2014 09:32:41 AM DEBUG This message should go to the log file _decorador
04/21/2014 09:32:41 AM INFO So should this _decorador
04/21/2014 09:32:41 AM WARNING And this, too _decorador
04/21/2014 10:46:23 AM DEBUG This message should go to the log file (debug) _decorador
04/21/2014 10:46:23 AM INFO So should this (info) _decorador
04/21/2014 10:46:23 AM WARNING And this, too (warning) _decorador

example.log中的所需输出:

04/21/2014 09:32:41 AM DEBUG This message should go to the log file mi_funcion
04/21/2014 09:32:41 AM INFO So should this mi_funcion
04/21/2014 09:32:41 AM WARNING And this, too mi_funcion
04/21/2014 10:46:23 AM DEBUG This message should go to the log file (debug) mi_funcion
04/21/2014 10:46:23 AM INFO So should this (info) mi_funcion
04/21/2014 10:46:23 AM WARNING And this, too (warning) mi_funcion

我的代码:

#!usr/bin/python3
# -*- coding: UTF-8 -*-

import logging

FORMAT = '%(asctime)s %(levelname)s %(message)s %(funcName)s'
logging.basicConfig(filename='example.log', level=logging.DEBUG, format=FORMAT, datefmt='%m/%d/%Y %I:%M:%S %p')

# Decorator function, writes in the log file.
def decorador(funcion):
    def _decorador(*args, **kwargs):
        funcion(*args, **kwargs)
        logging.debug('This message should go to the log file (debug)')
        logging.info('So should this (info)')
        logging.warning('And this, too (warning)')
    return _decorador

    @decorador
def mi_funcion(arg1, arg2):
    print("Code asset: %s; Registry number: s%" % (arg1, arg2))

mi_funcion("18560K", 12405)

2 个答案:

答案 0 :(得分:1)

你无法轻易改变这一点。记录模块funcName的目标是报告源代码行的确切位置,而不是它所代表的函数。我们的想法是,您将它与linenofilename条目结合使用,以查明源代码,而不是调用的函数。

为了实现这一点,日志模块使用代码对象内省来确定实际的函数名称:

def findCaller(self):
    """
    Find the stack frame of the caller so that we can note the source
    file name, line number and function name.
    """
    f = currentframe()
    #On some versions of IronPython, currentframe() returns None if
    #IronPython isn't run with -X:Frames.
    if f is not None:
        f = f.f_back
    rv = "(unknown file)", 0, "(unknown function)"
    while hasattr(f, "f_code"):
        co = f.f_code
        filename = os.path.normcase(co.co_filename)
        if filename == _srcfile:
            f = f.f_back
            continue
        rv = (co.co_filename, f.f_lineno, co.co_name)
        break
    return rv

如果没有重建_decorador代码对象,则无法更改此处报告的内容。可以完成重构代码对象;例如,您可以使用调用装饰器的exec构建外观函数。但为了实现这个目的,带有一个闭包是比你应该担心的更多的工作,真的。

我改为包含包装函数的函数名称:

logging.debug('This message should go to the log file (debug) (function %r)', 
              funcion)

答案 1 :(得分:1)

您可以从funcion对象中提取函数名称:

def decorador(funcion):
    def _decorador(*args, **kwargs):
        funcion(*args, **kwargs)
        logging.debug('This message should go to the log file (debug) %s',
                funcion.__name__)
        # ...
    return _decorador

运行修改后的代码后得到此输出:

cat example.log
04/21/2014 11:37:12 AM DEBUG This message should go to the log file (debug) mi_funcion