2012-04-29 3 views
3

다음 두 모듈 prog.py 및 err.py를 고려하십시오. 이 두 가지 모두이 문제를 나타내는 더 큰 프로그램의 예입니다. 기능을 테스트 벤치가있는 작은 소스 파일로 분리해야합니다.예외 처리기가 별도의 모듈에있는 예외

Err.py에는 테스트 벤치가 포함됩니다. 예외가 호출되는 방법에 따라 prog 객체를 만들면 예외가 catch됩니다.

"from err import *"문에서 prog.py가 err 객체를 가져 오더라도 모듈 이름이 여전히 추측됩니다 (잘못 되었습니까?)하지만 참조하는 오류가 해당 오류와 같지 않은 것처럼 보입니다. 모듈 자체

이것은 Python 2.7의 버그입니까? 아니면 의도 된 동작입니까?

#prog.py 

from err import * 



class prog(object): 
    def func1(self): 
     raise MySubError 

    def func2(self): 
     doError() 

그리고 두 번째 파일 :

#err.py 
import prog 
import inspect 
import sys 

class myError(Exception): 
    pass 

class MySubError(myError): 
    pass 

def doError(): 
    raise MySubError 

if __name__=="__main__": 

    p=prog.prog() 


    try: 
     doError() 
    except MySubError as er: 
     print type(er) 
     print "Captured 1" 
    except Exception as er: 
     print type(er) 
     print "Not Captured 1"   

    try: 
     p.func1() 
    except MySubError as er: 
     print type(er) 
     print "Captured 2" 
    except Exception as er: 
     print type(er) 
     print "Not captured 2" 


    try: 
     p.func2() 
    except MySubError as er: 
     print type(er) 
     print "Captured 3" 
    except Exception as er: 
     print type(er) 
     print "Not captured 3" 

그것은 보인다

단순히

첫 번째 파일은 .. 두 파일을 얻을 내가 무엇을 의미하는지에 관해 알기 위해 err.py를 실행 마치 어떤 식 으로든 오류가있는 모듈이 무엇인지 알아야하며 예외는 MySubError가 아니라 err.MySubError 여야합니다. 나는 모듈을 얻을 수 있지만 인스턴스 .....

출력 할 수 있습니다 : 여기

<class '__main__.MySubError'> 
Captured 1 
<class 'test.MySubError'> 
Not captured 2 
<class 'test.MySubError'> 
Not captured 3 

답변

1

파이썬은 err.py이 주 스크립트와 동일하다는 것을 모르는 것이 문제입니다. 일반적으로 모듈은 한 번만 가져 오지만 기본 스크립트가 모듈로 가져 오면 Python은 혼란스럽고 실제로는 err.py을 두 번로드합니다. (나는 그것에 대한 어떤 좋은 이유도 알지 못했을 것입니다; 아마도 @Latty가 더 구체적 일 수 있습니다).

는이 간단한 스크립트로 문제를 볼 수 있습니다

# File: recur.py 
import recur 
print "This is the module" 

if __name__ == '__main__': 
    print "This is main" 

당신이 그것을 실행하면 당신은 모듈은 한 번만 가져 오기 때문에하지는 무한 재귀를 얻을. 그러나 "This is the module"이 두 번 보일 것입니다.

주 스크립트가 직접 또는 간접적으로 가져 오기되지 않는 한 한 모듈에서 다른 모듈로 예외를 가져 오는 데는 아무런 문제가 없습니다. 두 개의 상호 의존적 인 모듈 A와 B가 각각 다른 모듈을 가져 오는 데는 아무런 문제가 없습니다 : import A을 시도하면 각 모듈이 한 번만로드된다는 것을 알 수 있습니다.

편집 : 난 정말 당신이 모듈로 메인 스크립트를 수입하지 않도록해야한다고 생각하지만, 나는 당신의 예를 들어 수정의 생각 :

# err.py 
... 
if __name__=="__main__": 
    from prog.err import *  # add this line 

이 모든 중복 스크립트 클래스를 대체 할 자신의 모듈 버전 등 모든 것이 의도 한대로 작동합니다.

+0

예이 사실을 알고 있으며 그것은 의미가 있습니다. 이 예외가 변경되는 클래스 이름 지정이 의미가 없습니다. 나는 아직도 그것에 대한 이유를 볼 수 없다. 결국 궁극적으로는 동일한 클래스 인스턴스입니다. 나는 exec를 사용하지 않았다, 나는 방금 모듈 함수 testerr.TestError()를 사용하여 두 모듈에서 호출했다. 그런 식으로 전역 테스트 모듈과 함께 작동 할 것이다. –

+0

Jason :하지만 코드를 구조화 한 방식을 감안할 때 동일한 클래스 인스턴스는 아닙니다. 아마도 Latty와 alexis는 내가 틀렸다면 나를 바로 잡을 수는 있겠지만, prog.py 내부에서''잘못 가져 오기 * '를하고 있기 때문에 prog.py 내부의''err.py' '에있는 모든 것을 로컬 복사본으로 만듭니다. py'. 그래서 prog.py에서 예외 클래스의 이름은'err.MySubError'이며, err.py 내부에는'__main __. MySubError'라는 이름이 붙습니다. 저는 당신이'raise '가 어디에 있느냐에 따라 실제로 두 가지 예외를 제기한다고 생각합니다. – alan

+0

@alan, 틀렸어. :-) 하나의 일반 모듈에서 다른 모듈로 예외를 가져 오는 것은 예상대로 작동하지만, 나는 그것을 과거에 시도해 보았습니다. 문제는 파이썬이 스크립트가 모듈과 동일하다는 것을 인식하지 못한다는 것입니다. 내가 상상할 수있는 유일한 변명은 : 스크립트 이름은 유효한 모듈 이름 일 필요는 없으며, 모듈 가져 오기 경로에 아무 것도 없다. 그래서 파이썬은 그것들을 추적 할 좋은 방법이 없다. – alexis

2

문제는 err 실제로 두 개의 서로 다른 모듈 역할을한다는 것입니다, 기본적으로.

파이썬에서 실행되는 기본 모듈은 __main__입니다. 실행 된 모든 것이 네임 스페이스에 저장됩니다. 여기서 일어나는 일은 모듈을 다른 스크립트로 가져 오는 것입니다.이 모듈을 err이라고 부르므로 같은 것으로 간주되지 않습니다.

다소 이상하지만, Python 가져 오기 시스템이 일관되게 작동하는 방식을 유지해야합니다. 가장 좋은 대답은 __main__이라는 스크립트 외부에서 예외를 이동하는 것입니다. 어쨌든 좋은 디자인입니다. 본질적으로 여기서 순환 가져 오기를 작성하고 있기 때문입니다.

+0

그래서 err.py 대신 err.py 및 testerr.py가 있어야합니까? 문제는 모든 모듈이 그 안에 테스트 픽스쳐를 가져야한다는 규칙이 있다는 것입니다. exec()를 사용하여 err 테스트 하네스를 호출 할 수 있다고 생각하지만 약간 해킹 될 수 있습니다. –

+0

좋아, 나는 그것을 좋아하지 않는다. 그것은 내게 비합리적인 것처럼 보인다. MySubError는 형식을 유지해야하며 가져온 방법으로 인해 이름이 변경되지 않으므로 예외가 발생합니다. 하지만 저에게 다시 알려면 err에서 testerr을 가져 와서 테스트 함수가 모든 시냅스에서 작동한다는 것을 발견 했으므로 모듈 테스트를 외부로 옮기셔서 기쁩니다. –

+1

확실히'exec()'을 사용하지 마십시오. 그러면 별칭 문제가 악화됩니다. 스크립트 자체를 가져 오는 것을 피하면 원하는대로 작동합니다. 파이썬은 수입품 전체에 걸친 네임 스페이스를 잘 관리하고 있습니다. – alexis