Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用decorator的Python日志记录_Python_Logging_Introspection_Decorator - Fatal编程技术网

使用decorator的Python日志记录

使用decorator的Python日志记录,python,logging,introspection,decorator,Python,Logging,Introspection,Decorator,这是我们在面对装饰师时遇到的第一个例子。但我不知道我到底想要什么 一个名为LOG的简单装饰器。它应该是这样工作的: @LOG def f(a, b=2, *c, **d): pass def LOG(fn): import inspect varList, _, _, default = inspect.getargspec(fn) d = {} if default is not None: d = dict((varList[-len

这是我们在面对装饰师时遇到的第一个例子。但我不知道我到底想要什么

一个名为LOG的简单装饰器。它应该是这样工作的:

@LOG
def f(a, b=2, *c, **d):
    pass
def LOG(fn):
    import inspect
    varList, _, _, default = inspect.getargspec(fn)
    d = {}
    if default is not None:
        d = dict((varList[-len(default):][i], v) for i, v in enumerate(default))
    def f(*argt, **argd):
        print ('Enter %s' % fn).center(100, '=')
        d.update(dict((varList[i], v) for i, v in enumerate(argt)))
        d.update(argd)
        for c in d.iteritems():
            print '%s = %s' % c
        ret = fn(*argt, **argd)
        print 'return: %s' % ret
        print ('Exit %s' % fn).center(100, '=')
        return ret
    return f
结果应该是:

f(1, pippo=4, paperino='luca')
===== Enter f =====
a = 1
b = 2
pippo = 4
paperino = luca
===== Exit f =====
其中,作为参数传递给函数的每个参数都显示其值

我发现这个问题比我想象的更难,主要是因为你可以用许多不同的方式将参数传递给函数(想想带*c的元组或带**d的字典)

我尝试了一个解决方案,但我不确定它是否正确。有人这样想:

@LOG
def f(a, b=2, *c, **d):
    pass
def LOG(fn):
    import inspect
    varList, _, _, default = inspect.getargspec(fn)
    d = {}
    if default is not None:
        d = dict((varList[-len(default):][i], v) for i, v in enumerate(default))
    def f(*argt, **argd):
        print ('Enter %s' % fn).center(100, '=')
        d.update(dict((varList[i], v) for i, v in enumerate(argt)))
        d.update(argd)
        for c in d.iteritems():
            print '%s = %s' % c
        ret = fn(*argt, **argd)
        print 'return: %s' % ret
        print ('Exit %s' % fn).center(100, '=')
        return ret
    return f
我想这并不像我想象的那么容易,但奇怪的是,我没有在谷歌上找到我想要的东西

你能告诉我我的解决方案是否可行吗?或者你能为我提出的问题提出更好的解决方案吗


谢谢大家。

我注意到的唯一一件事是,
dict((varList[I],v)for I,v in enumerate(argt))
构造实际上是
dict(zip(varList,argt))

除此之外,我只有元批评:以上这些都不属于日志文件

而不是把原木扔到

  • 查看是否使用您使用的断言和调试器的正确参数调用函数
  • 查看函数是否返回您编写的unittests的正确结果

    • 您的功能一切正常。您似乎对位置参数、变量参数和关键字参数感到迷茫

      让我解释一下:在您的情况下,位置参数,
      a
      b
      是必须的(可能有默认值)。其他参数是可选的。如果您想使参数成为强制参数或具有默认值,请将其置于*args和**kwargs之前。但请记住,您不能提供两次论点:

      def x(a = 1, b = 2, *args, **kwargs):
          print a, b, args, kwargs
      
      >>> x(3, 4, 5, b=6)
      TypeError: x() got multiple values for keyword argument 'b'
      
      还有另一种方法,但可读性不高,可以为参数设置默认值,而不设置位置参数:

      def x(*args, **kwargs):
          kwargs.updae({'a': 1, 'b': 2})
      
      虽然我不明白为什么要将
      varargs
      keywords
      写入
      \uu
      中,但分析参数的函数是可以的。它透明地传递参数:

      def x(a = 1, b = 2, *args, **kwargs):
          print a, b, args, kwargs
      
      def y(*args, **kwargs):
          x(*args, **kwargs)
      
      >>> y(3, 4, 5, 6)
      3 4 (5, 6) {}
      
      >>> y(3, 4, 5, b=6)
      TypeError: x() got multiple values for keyword argument 'b'
      

      我发现,如果考虑到一般函数理论上可以返回iterable,在这种情况下会抛出一个错误,那么您的优秀解决方案可以稍加改进

      这里有一个解决方案:

      print'返回:%s'%ret
      包装到if语句中:
      如果hasattr(ret,“\uuuuu iter””):
      打印“返回的iterable”
      其他:
      打印“返回:%s”%ret


      通过这种方式,您既不需要花费大量时间打印大型可编辑文件,也可以根据需要进行修改。(字符串也没有方便的
      \uuu iter\uuu
      属性)

      它能工作吗?如果它起作用,那就没事了。如果没有,那么你就有问题了。问我们一个关于那个问题的具体问题。是的,你是对的。实际上,它似乎起作用了。但正如我所写的,有许多复杂的方法可以将参数传递给Python函数:使用元组、字典、默认参数。。。事实上,即使它似乎能工作,我也不确定它是否是正确的实现,它在任何情况下都能工作。我自己也曾是它的牺牲品,以您所描述的绝对通用的形式,这个函数是否是您继续开发应用程序所必需的?听起来日志机制本身吸引了你的注意力,我从经验中知道这可能是一个可怕的生产力杀手。我完全同意你的观点。继续工作对我来说并不重要。因为它不是那么重要,而且我无法解决这个问题,所以我把它移到了待办事项列表的底部。但现在这是一种锻炼。。。我想知道,对于我描述的问题,是否有一个通用的、优雅的、简单的解决方案。别担心,我的大脑也是这样工作的。我怀疑这个网站上还有很多其他人…你能详细说明/提供(1)的链接吗?谢谢你提供了有用的zip功能。我认为你的元批评是正确的。我在远程机器上开发,不能使用调试器。因此,这种日志记录方法应该是一种简单的调试方法。批评元批评:如果在生产中有缺陷,你会很乐意接受任何你能得到的日志。因此,所有这些信息都属于日志。