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

时间:2016-12-15 07:22:57

标签: python python-2.7 traceback getattribute

我已阅读this on SO之类的问题,我相信我理解使用__getattribute__的危险。但是,最近我接手了其他人的项目,我需要做一些修改。我认为理解项目的最好方法是跟踪它 - 所以我插入了pdb.set_trace()然后我按下了#34; n \ r \ n" - 但程序没有被执行到下一个行并等待新的输入,但继续执行一直到它的结束。搜索之后,我认为导致问题的是__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

正如你所看到的,我按下了&#34; n \ r \ n&#34;只有并且执行一直持续到程序完成。

还有一个小问题,如果我在没有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 个答案:

答案 0 :(得分:2)

pdb使用https://github.com/angular/flex-layout#api-overview设置跟踪功能来完成其工作。传播出跟踪功能的任何异常都会禁用它。 RuntimeError在trace函数内部发生,一旦发生就会关闭pdb。