开发者

Can you translate this debugging macro from C++ to python?

I use this very helpful macro when developing in C++:

#define DD(a) std::cout << #a " = [ " << a << " ]" << std::endl;std::cout.flush();

Could you help me implement the 开发者_如何转开发same idea in python? I don't know how the #a could be implemented with a python function...


As @Andrea Spadaccini and @adirau point out, it is not possible to reliably map values back to Python variable names. You could trawl through all namespaces looking for some variable name that references the given value, but that would be fighting the system and liable to return the wrong variable name.

Much easier it is to just pass the variable name:

import inspect
def pv(name):
    frame,filename,line_number,function_name,lines,index=inspect.getouterframes(
        inspect.currentframe())[1]    
    # print(frame,filename,line_number,function_name,lines,index)
    val=eval(name,frame.f_globals,frame.f_locals)
    print('{0}: {1}'.format(name, val))


a=5
pv('a')

yields:

a: 5


You could inspect the stack trace and "parse" it. Since you know the name of your function (dd in this case) it becomes fairly easy to find the call and extract the name of the variable.

    import inspect
    import re

    def dd(value):
        calling_frame_record = inspect.stack()[1]
        frame = inspect.getframeinfo(calling_frame_record[0])
        m = re.search( "dd\((.+)\)", frame.code_context[0])
        if m:
            print "{0} = {1}".format(m.group(1), value)

    def test():
        a = 4
        dd(a)

    test()

Output

a = 4


I think that this cannot be done.

The debugging macro that you posted works because it is expanded before compilation, during pre-processing, when you know the variable name. It is like you write all those couts by yourself.

Python does not have a pre-processor (AFAIK), there are external tools that do a similar thing (pyp and others), but you can not define a macro with the standard language.

So you should do your trick at run-time. Well, at run-time you don't know the "name" of the variable because the variable is just a reference to an object, when you call a method you call it on the object, not on the "variable". There can be many variables that point to that object, how does the object know which variable was used to call the method?


You can't get a variable (well, object)'s name in python. But you can pass the object's name to get its value (kinda the opposite of what you do with that macro)

>>> a=4
>>> locals()['a']
4

EDIT: a detailed explanation may be found here


import sys

def DD(expr):
    frame = sys._getframe(1)
    print '%s = %s' % (expr, repr(eval(expr, frame.f_globals, frame.f_locals)))

GLOBAL_VAR = 10

def test():
    local_var = 20
    DD('GLOBAL_VAR + local_var')


>>> test()
GLOBAL_VAR + local_var = 30


The Rod solution is perfectly usable. It could be even extended to handle many vars. But you can get close to that with much less magic:

def dd(**kwargs):
    print ", ".join(str(k) + "=" + str(v) for k, v in kwargs.iteritems())

a = 1
dd(a=a,b=3)

output:

a=1, b=3
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜