你会如何在python中编写一个@debuggable装饰器?

Phi*_*l H 9 python decorator

调试时,我喜欢打印出函数的所有输入和输出(我知道我需要一个更好的IDE,但是幽默我,这可以用于错误报告).所以,我最好喜欢:

@debuggable
def myfunc(argA,argB,argC):
    return argB+1
Run Code Online (Sandbox Code Playgroud)

并使用全局变量来打开或关闭调试.不,我猜你也不喜欢全局变量.

我能想到的最好的是:

DEBUG = True

def debuggable(func):
    if DEBUG:
        def decorated(*args):
            print "Entering ",func.func_name
            print "    args ",args
            ret = func(*args)
            print ret
            return ret
        return decorated
    else:
        return func

@debuggable
def myfunc(this,that):
    return this+that
Run Code Online (Sandbox Code Playgroud)

并运行:

>>> myfunc(1,3)
Entering  myfunc
   args  (1, 3)
4
Run Code Online (Sandbox Code Playgroud)

我怎样才能改善这一点?

nos*_*klo 23

使用调试器.认真.装饰你想要跟踪的每个功能是一个坏主意.

Python 包含一个调试器,因此您不需要一个好的IDE.

如果您不想使用调试器,则可以使用跟踪功能.

import sys

@sys.settrace
def trace_debug(frame, event, arg):
    if event == 'call':
        print ("calling %r on line %d, vars: %r" % 
                (frame.f_code.co_name, 
                 frame.f_lineno,
                 frame.f_locals))
        return trace_debug
    elif event == "return":
        print "returning", arg

def fun1(a, b):
    return a + b

print fun1(1, 2)
Run Code Online (Sandbox Code Playgroud)

打印:

calling 'fun1' on line 14, vars: {'a': 1, 'b': 2}
returning 3
3
Run Code Online (Sandbox Code Playgroud)

更容易使用Winpdb:

它是一个独立平台的图形GPL Python调试器,支持通过网络进行远程调试,多线程,命名空间修改,嵌入式调试,加密通信,速度比pdb快20倍.

特征:

  • GPL许可证.Winpdb是免费软件.
  • 兼容CPython 2.3或更高版本.
  • 与wxPython 2.6或更高版本兼容.
  • 独立于平台,并在Ubuntu Gutsy和Windows XP上进行了测试.
  • 用户界面:rpdb2是基于控制台的,而winpdb需要wxPython 2.6或更高版本.

截图http://winpdb.org/images/screenshot_winpdb_small.jpg


Joh*_*ery 11

我认为你所追求的并不是真正的调试装饰者,而是更多的日志装饰者.

使用Python的日志记录模块可能有意义,因此您可以对日志记录本身进行更细粒度的控制.例如,您可以输出到文件以便以后分析输出.

装饰者可能看起来更像是:


import logging

logger = logging.getLogger('TraceLog')
# TODO configure logger to write to file/stdout etc, it's level etc


def logthis(level):
    def _decorator(fn):
        def _decorated(*arg,**kwargs):
            logger.log(level, "calling '%s'(%r,%r)", fn.func_name, arg, kwargs)
            ret=fn(*arg,**kwargs)
            logger.log(level, "called '%s'(%r,%r) got return value: %r", fn.func_name, arg, kwargs, ret)
            return ret
        return _decorated
    return _decorator

@logthis(logging.INFO)
def myfunc(this,that):
    return this+that

然后,如果您将记录器配置为输出到stderr,您会看到:


>>> logger.setLevel(logging.INFO)
>>> handler=logging.StreamHandler()
>>> logger.addHandler(handler)
>>> myfunc(1,2)
calling 'myfunc'((1, 2),{})
called 'myfunc'((1, 2),{}) got return value: 3


Nad*_*mli 8

我同意使用调试器的nosklo比编写自己的调试器要好得多.我将对您的代码发布一项改进.但我仍然认为你应该遵循nosklo的建议.

使用装饰器类使您的调试器更整洁:

class Debugger(object):
    enabled = False
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        if self.enabled:
            print 'Entering', self.func.func_name 
            print '    args:', args, kwargs
        return self.func(*args, **kwargs)

Debugger.enabled = True

@Debugger
def myfunc(a, b, c, d):
    pass
Run Code Online (Sandbox Code Playgroud)