代码之家  ›  专栏  ›  技术社区  ›  Junchao Gu

了解__getattribute__和pdb。set_trace()以Python代码片段为例

  •  -1
  • Junchao Gu  · 技术社区  · 8 年前

    我读过这样的问题 this on SO 我相信我理解使用的危险 __getattribute__ __获取属性__ 造成问题,但我不知道为什么。我将代码简化为以下内容:

    class TestAttribute(object):
        """docstring for TestAttribute"""
        def __init__(self, is_testing=False):
            super(TestAttribute, self).__init__()
            self.is_testing = is_testing
    
        def __getattribute__(self, name):
            # print(name)
            try:
                # the line below will trigger the recursion error
                if self.is_testing:
                    name = name.upper()
                return super(TestAttribute, self).__getattribute__(name)
            except AttributeError:
                return None
            except Exception:
                # this line is added by me to see the output
                import traceback; traceback.print_exc();
                return None
    
        def __getitem__(self, name):
            return self.__getattribute__(name)
    
        def __setitem__(self, name, val):
            return self.__setattr__(name, val)
    
        def __setattr__(self, name, val):
            # so this func will be called in __init__ and will
            # enter __getattribute__
            if self.is_testing:
                name = name.lower()
            super(TestAttribute, self).__setattr__(name, val)
    
    
    if __name__ == '__main__':
        ttt = TestAttribute()
        import pdb; pdb.set_trace()
        ttt.k = 1
        print('test done')
        print('test done again')
        print('test done again')
        print('test done again')
    

    输出如下:

    Traceback (most recent call last):
      File "test_getattribute.py", line 10, in __getattribute__
    Traceback (most recent call last):
      File "test_getattribute.py", line 10, in __getattribute__
        if self.is_testing:
      File "test_getattribute.py", line 16, in __getattribute__
        import traceback; traceback.print_exc();
      File "/usr/lib/python2.7/traceback.py", line 232, in print_exc
        print_exception(etype, value, tb, limit, file)
      File "/usr/lib/python2.7/traceback.py", line 125, in print_exception
        print_tb(tb, limit, file)
      File "/usr/lib/python2.7/traceback.py", line 69, in print_tb
        line = linecache.getline(filename, lineno, f.f_globals)
      File "/home/jgu/repos/.venv/lib/python2.7/linecache.py", line 14, in getline
        lines = getlines(filename, module_globals)
      File "/home/jgu/repos/.venv/lib/python2.7/linecache.py", line 40, in getlines
        return updatecache(filename, module_globals)
    RuntimeError: maximum recursion depth exceeded
    > /home/jgu/repos/dat_cs/test_getattribute.py(34)<module>()
    -> ttt.k = 1
    (Pdb) n
    Traceback (most recent call last):
      File "test_getattribute.py", line 10, in __getattribute__
        if self.is_testing:
      File "test_getattribute.py", line 7, in __getattribute__
        def __getattribute__(self, name):
      File "/usr/lib/python2.7/bdb.py", line 50, in trace_dispatch
        return self.dispatch_call(frame, arg)
      File "/usr/lib/python2.7/bdb.py", line 76, in dispatch_call
        if not (self.stop_here(frame) or self.break_anywhere(frame)):
      File "/usr/lib/python2.7/bdb.py", line 147, in break_anywhere
        return self.canonic(frame.f_code.co_filename) in self.breaks
      File "/usr/lib/python2.7/bdb.py", line 29, in canonic
        if filename == "<" + filename[1:-1] + ">":
    RuntimeError: maximum recursion depth exceeded in cmp
    test done
    test done again
    test done again
    test done again
    

    如您所见,我只按了“n\r\n”,执行一直持续到程序结束。

    还有另一个小问题,如果我在没有pdb的情况下运行,我会看到以下输出:

    Traceback (most recent call last):
      File "test_getattribute.py", line 10, in __getattribute__
    Traceback (most recent call last):
      File "test_getattribute.py", line 10, in __getattribute__
        if self.is_testing:
      File "test_getattribute.py", line 16, in __getattribute__
        import traceback; traceback.print_exc();
      File "/usr/lib/python2.7/traceback.py", line 232, in print_exc
        print_exception(etype, value, tb, limit, file)
      File "/usr/lib/python2.7/traceback.py", line 125, in print_exception
        print_tb(tb, limit, file)
      File "/usr/lib/python2.7/traceback.py", line 69, in print_tb
        line = linecache.getline(filename, lineno, f.f_globals)
      File "/home/jgu/repos/.venv/lib/python2.7/linecache.py", line 14, in getline
        lines = getlines(filename, module_globals)
      File "/home/jgu/repos/.venv/lib/python2.7/linecache.py", line 40, in getlines
        return updatecache(filename, module_globals)
    RuntimeError: maximum recursion depth exceeded
    Traceback (most recent call last):
    Traceback (most recent call last):
      File "test_getattribute.py", line 10, in __getattribute__
        if self.is_testing:
      File "test_getattribute.py", line 16, in __getattribute__
        import traceback; traceback.print_exc();
      File "/usr/lib/python2.7/traceback.py", line 232, in print_exc
        print_exception(etype, value, tb, limit, file)
      File "/usr/lib/python2.7/traceback.py", line 125, in print_exception
        print_tb(tb, limit, file)
      File "/usr/lib/python2.7/traceback.py", line 67, in print_tb
        '  File "%s", line %d, in %s' % (filename, lineno, name))
    RuntimeError: <unprintable RuntimeError object>
    test done
    test done again
    test done again
    test done again
    

    所以第二个错误没有正确打印,这是为什么?

    编辑: 我并不是在问为什么会出现递归错误。我相信这一点我很清楚,所以请先理解我的问题。谢谢

    1 回复  |  直到 8 年前
        1
  •  2
  •   user2357112    8 年前

    pdb使用 sys.settrace

    推荐文章