2016-12-15 8 views
-1

this on SO과 같은 질문을 읽었으며 __getattribute__을 사용하는 위험을 이해하고 있습니다. 그러나 최근에는 다른 사람들의 프로젝트를 인수했고 수정해야합니다. 나는 프로젝트를 이해하는 가장 좋은 방법은 그것을 추적하는 것이라고 생각한다. 그래서 pdb.set_trace()를 삽입하고 "n \ r \ n"을 눌렀다. 그러나 프로그램은 다음 줄로 실행되지 않고 새로운 것을 기다린다. 대신 입력을 끝까지 계속 실행하십시오. 검색을 한 후에는 문제의 원인이되는 __getattribute__의 오용이라고 생각하지만 이유는 알 수 없습니다. 아래예를 들어 파이썬 코드 스 니펫을 사용하여 __getattribute__ 및 pdb.set_trace()를 이해하십시오

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 

이 왜

입니다?

편집 : 왜 재귀 오류가 발생하는지 묻지 않습니다. 나는 그 부분에 내가 분명하다고 믿는다. 그래서 제 질문을 먼저 이해해주십시오. 감사합니다

+0

'if self.is_testing' - 글쎄, 어떻게'self.is_testing' 값을 찾았습니까? 당신은'__getattribute__'를 호출합니다. '__getattribute__'를 실행하려면, 먼저'self.is_testing'를 체크하십시오. 'self.is_testing'의 가치를 어떻게 찾으십니까? 당신은'__getattribute__'를 호출합니다 ... – user2357112

+0

왜 재귀 오류가 발생하는지 묻지 않습니다. 나는 그 부분에서 내가 분명하다고 생각한다. –

답변

2

pdb는 sys.settrace을 사용하여 추적 기능을 설정하여 작업을 수행합니다. 추적 기능에서 전파되는 예외는이를 사용 불가능하게합니다. RuntimeError는 추적 기능 내에서 발생하며, 일단 발생하면 pdb를 근본적으로 끕니다.

+0

알았는데. 설명 해줘서 고마워. 두 번째 질문은 어떻습니까? –

+0

@JunchaoGu : RuntimeError를 잡았을 때 스택이 여전히 미친 데다가 스택 트레이스를 표시하려고 할 때 * 다른 스택 오버플로가 발생했을 때 [특정 대체] (https://hg.python.org/cpython/file/2.7/Lib/traceback.py#l212). – user2357112

+0

그건 그렇고, 당신은 정말로 그 예외를 '__getattribute__'에 잡아서는 안됩니다. – user2357112