【问题标题】:Can you translate this debugging macro from C++ to python?你能把这个调试宏从 C++ 翻译成 python 吗?
【发布时间】:2011-07-27 01:52:39
【问题描述】:

我在使用 C++ 开发时使用了这个非常有用的宏:

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

你能帮我在 python 中实现同样的想法吗?我不知道#a 怎么可以用python函数来实现...

【问题讨论】:

  • 完全偏离主题:std::endl;std::cout.flush(); 为什么会这样? std::endl 自行刷新流。
  • 标准中有这个吗?
  • Yes, 27.7.3.8 下, [ostream.manip], endl: Effects: Calls os.put(os.widen(’\n’)), then os.flush().

标签: c++ python debugging logging macros


【解决方案1】:

Rod 解决方案非常实用。 它甚至可以扩展到处理许多变量。 但是你可以用更少的魔法接近它:

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

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

输出:

a=1, b=3

【讨论】:

    【解决方案2】:
    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
    

    【讨论】:

      【解决方案3】:

      您可以检查堆栈跟踪并“解析”它。由于您知道函数的名称(在本例中为 dd),因此很容易找到调用并提取变量的名称。

          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()
      

      输出

      a = 4
      

      【讨论】:

        【解决方案4】:

        正如@Andrea Spadaccini@adirau 指出的那样,不可能将值可靠地映射回Python 变量名。您可以在所有命名空间中查找引用给定值的变量名,但这会与系统发生冲突并可能返回错误的变量名。

        只传递变量名要容易得多:

        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')
        

        产量:

        a: 5
        

        【讨论】:

          【解决方案5】:

          您无法在 python 中获取变量(嗯,对象)的名称。但是您可以传递对象的名称来获取它的值(有点与您使用该宏所做的相反)

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

          编辑:可以找到详细解释here

          【讨论】:

            【解决方案6】:

            我认为这是不可能的。

            您发布的调试宏之所以有效,是因为它在编译之前、预处理期间、当您知道变量名称时进行了扩展。就像你自己写的所有couts。

            Python 没有预处理器 (AFAIK),有一些外部工具可以做类似的事情(pyp 和其他),但是您不能使用标准语言定义宏。

            所以你应该在运行时做你的伎俩。好吧,在运行时您不知道变量的“名称”,因为变量只是对对象的引用,当您调用方法时,您在对象上调用它,而不是在“变量”上。可以有很多变量指向那个对象,对象怎么知道哪个变量被用来调用方法?

            【讨论】:

            • 然而,也许一位 Python 专家 会进来向我们展示如何做到这一点.. 我很好奇! :)
            • 没有。就连圭多本人也做不到。从一个对象到引用它的 0..infinity 名称没有链接。并且没有(干净和/或可取的)方法来规避词法作用域并进入调用者的命名空间。
            猜你喜欢
            • 1970-01-01
            • 2020-09-19
            • 2011-05-20
            • 2010-09-12
            • 2010-10-10
            • 2021-10-05
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多