2009-05-08 4 views
51

예외를 만드는 가장 좋은 방법은 무엇입니까? 나는 이것을 단지 보았고, 내가 소름 끼치거나 좋아할 지 모르겠습니다. 문자열 자체가 예외를 throw 할 수 있기 때문에 예외가 절대 문자열을 보유해서는 안되는 책을 여러 번 읽었습니다. 이거 진짜 진실이야?Python 예외에 대한 유용한 정보

기본적으로 필자가 이해 한 내용은 이것이 모든 내부 Python 라이브러리가 오류 메시지 형식 (필자가 필요로하는 일반적인 오류 메시지 형식)을 갖춰서 오류 메시지 문자열을 넣는 것이 좋은 생각인지 이해할 수 있다는 것입니다. . (거의 모든 메소드는 유효하지 않은 무언가를 완전히 필요로하기 때문에 예외를 던집니다.) 이것은 빙산의 일각이다

""" 
Base Exception, Error 
""" 
class Error(Exception): 
    def __init__(self, message): 
     self.message = message 

    def __str__(self): 
     return "[ERROR] %s\n" % str(self.message) 

    def log(self): 
     ret = "%s" % str(self.message) 
     if(hasattr(self, "reason")): 
      return "".join([ret, "\n==> %s" % str(self.reason)]) 
     return ret 

class PCSException(Error): 
    def __init__(self, message, reason = None): 
     self.message = message 
     self.reason = reason 
    def __str__(self): 
     ret = "[PCS_ERROR] %s\n" % str(self.message) 
     if(self.reason != None): 
      ret += "[REASON] %s\n" % str(self.reason) 
     return ret 

하지만, 누군가가 나에게이 끔찍한 생각하는 무슨에 몇 가지 통찰력을 제공 할 수 있습니다 :

문제의 코드는 다음과 같다? 또는 코딩 프로세스/스타일이 훨씬 더 우수합니다.

+0

나는 프로그래머에게 최대한의 정보를 제공하기 위해 최대한의 예외 계층 구조를 갖는 것이 가장 좋은 방법이라고 생각한다. 예를 들어 (아래부터) WrongInputError -> InputError -> GeneralInputError -> NonCriticalError -> Error -> GeneralError -> BaseError -> WhyIsThisHappeningerror와 같은 것을 권장합니다. – drozzy

답변

28

나는 문자열 때문에 스스로 할 수 던져 예외 예외 적 문자열을 보유해서는 안 책에서 여러 번 읽어 보시기 바랍니다. 이 진정한 진실은 입니까?

무엇?

여기에 대한 참조 또는 링크를 제공해주십시오. 그것은 완전히 거짓입니다.

모든 개체가 예외를 throw 할 수 있으므로 해당 논리에 의해 예외에 개체가 포함될 수 없습니다.

아니요, "문자열 없음"은 파이썬 컨텍스트에서 단순히 미친 것입니다. 아마도 당신은 C++ 문맥에서 그것을 읽었을 것입니다.


편집

일단 (다시 옛날에) 시간이 이름 대신 실제 클래스 파이썬 예외를 발생시킬 수에 따라.

raise "SomeNameOfAnExceptionClass" 

이것은 좋지 않습니다. 그러나 이것은 이 아니고 예외 내에있는 문자열을 포함하는이 아닙니다. 이것은 실제 클래스 객체 대신 문자열을 사용하여 예외의 이름을 지정합니다. 2.5에서는 여전히 작동 할 수 있지만 비추천 경고가 표시됩니다.

아마도 이것은 당신이

+0

당신의 바로 지금 나는 그것에 대해 생각합니다. 그들 중 대부분은 C++ 책 이었지만 파이썬 책을 읽었을 때 대담한 글자로 "예외는 절대로 오류 메시지를 담아서는 안되며 작은 식별자 (숫자 또는 작은 문자열) 만 가져야합니다"라고 말한 것을 분명히 기억합니다. 그 책을 기억하지는 않겠지 만, 내가 그걸 파낼 수 있는지 알게 될 것이다. – UberJumper

+5

아마도 예외적 인 여러 상황에 Exception 클래스를 사용해서는 안된다는 사실을 언급했을 수도 있습니다. MyFrameworkException ('파일을 찾을 수 없음') 및 MyFrameworkException ('데이터베이스 연결을 사용할 수 없음')과 같습니다. –

+0

+1 예외 상황에있는 문자열은 매우 유용합니다. 파이썬 외의 다른 언어는 오류 생성자 또는 예외에 설명 정보를 추가하는 것을 지원합니다 ... "컨텍스트"또는 "이유"라고 할 수 있으며이를 문자열이나 다른 객체로 나타낼 수도 있지만 여전히 동일한 거래입니다 . –

3

첫 인상이 완전히 너무 많은 코드가 예외라는 것이다 "문자열 이름으로 예외를 발생하지 마십시오"를 읽어 것입니다.

형식 예외는 로거 구성에서 수행해야합니다. 로깅 자체에 대해서도 마찬가지입니다.

또한 표준 (및 비추천) 메시지 속성을 다시 정의하고 수퍼 클래스 생성자를 호출하지 않습니다. (이것은 파이썬 3.0 예외 체인을 깨뜨릴 수도,하지 않을 수도 있습니다. 2.6을 실행 중이기 때문에 시도하지 않았습니다)

BaseException을 사용하여 대부분의 코드를 구현할 수 있습니다.인수는 "메시지"로 다음을 로그인하여 :

'\n==> '.join(exception.args) 

뭔가 공통/관용적 메커니즘을 사용하여 수행 할 수 있다면, 그것은 특히 예외 처리에서 그렇게되어야한다고 주장 할 것입니다. (예외는 메커니즘이 애플리케이션 레이어에서 뭔가 을 신호하는 것.)

개인적으로

, 나는

class SomeException(Exception): pass 

이상 아무것도 피하려고 (면책 조항 :. 아마도 문제의 본질적으로 주관적인 답변)

+0

로거의 주된 문제점은 스크립트 중 일부는 20-30 줄과 비슷하다는 것입니다. – UberJumper

+0

포맷팅을 외부화하고 오류에 대한 정의를 기록하는 것처럼 로그 구성을 공유 모듈에 외부화 할 가능성이 있습니다. 우려의 분리는 보통 절대적인 코드 크기와 충돌하는 경향이 있습니다. – millimoose

+0

당신이 언급 한 것처럼 단순한 클래스를 넘어서는 아무것도 사용하지 않습니다. ** ** 포맷팅 예외는 간단하고 이해하기 쉬운 예제로 로거 설정 ._ **에서해야합니다. 감사합니다. –

73

Robust exception handling (in Python) - "파이썬 예외에 대한 모범 사례"블로그 게시물 얼마전에 썼습니다. 유용 할 수 있습니다. 블로그에서

핵심 사항 : 이벤트 정상적인 실행의 일부가 아닌 :

예외는 예외적 인 상황에 존재하는 흐름 제어에 대한 예외를 사용하지 마십시오.

는 반환 -1 패턴이 발견되지 않는 경우 문자열에 '찾기'고려하지만, 문자열의 끝을 넘어 인덱싱 예외를 발생시킵니다. 문자열을 찾지 못하면 정상적인 실행입니다. 그들에게

을 처리하는 방법을 알고있는 수준에서

핸들 예외 ...

가장 좋은 장소는 예외를 처리 할 수있는 코드의 조각이다. 프로그래밍 오류 (예 : IndexError, TypeError, NameError 등)와 같은 일부 예외는 프로그래머/사용자에게 가장 바람직합니다. 예외를 처리하면 실제 버그를 숨길 수 있기 때문입니다.

항상 "이 예외를 처리하기에 적합한 곳입니까?" 모든 예외를 포착하는 데주의하십시오.

문서 생각 코드

에 의해 던져진 예외 ...

하는 예외에 대한 더 나은 쓰기 도움이 될 것 던질 수 코드,보다 안전하고 캡슐화 된 코드

+3

외부 링크의 개요. – dbn

+4

이 답변이 게시 된 2009 년에 습관적이었던 것을 기억하지 못합니다. :-) 편집을 제안하십시오. –

+1

그럼에도 불구하고 그의 기사는 전체적으로 읽을 가치가 있으며이 질문에 답하는 데 소중한 공헌을합니다. –

4

문자열을 사용하여 예외를 작성하는 것에 대한 조언은 "Learning Python"(O'Reilly)에서 비롯된 것이라고 생각합니다. 섹션에서 문자열 예외가 발생했습니다., 임의의 문자열로 직접 예외를 생성하는 기능을 삭제했습니다.

는 예로서 제공하는 코드는 다음과 같습니다

myexc = "My exception string" 
try: 
    raise myexc 
except myexc: 
    print ('caught') 

이 4 판 (종이 표지)의 p858에 있습니다.

관련 문제