2014-11-25 4 views
2

현재 예외를 잡아내는 코드를 작성하려고하고 있으며 어떤 예외가 던져 졌는지에 따라 예외가 발생하지 않은 경우와 다른 모듈을 가져옵니다.파이썬 예외 잡기 및 별도의 메시지 인쇄

try: 
    import sge_execution_engine as execution_engine 
except ImportError: 
    print "Use local execution engine because SGE support is missing!" 
    print sys.exc_info() # Print out the exception message 
    import local_execution_engine as execution_engine 
except RuntimeError: 
    print "Using local execution engine because SGE support is missing!" 
    print sys.exc_info() 
    import local_execution_engine as execution_engine 

제 예외 잡힌 ImportError는 (sge_execution_engine 내부 import drmaa 문있다) 파이썬 drmaa 모듈 import sge_execution_engine 실행 중에 발견 될 수 없을 때 발생 예외를 잡는다. 두 번째 예외 인 RuntimeErrordrmaa 파이썬 라이브러리 (sge_execution_engine 내부의 import drmaa 문 실행 중 비슷 함)를 찾았지만 drmaa C 라이브러리가 OS에 설치되어 있지 않으면 포착됩니다. 이 두 개의 except 문이 파이썬 drmaa 라이브러리, drmaa C 라이브러리가 없거나 Sun Grid가없는 시스템에서이 모듈을 실행하려고 할 때 발생할 수있는 모든 예외를 포착하기에 충분해야합니다. 엔진이 설치되었습니다. 이러한 수익금이 없으면 모듈은 import local_execution_engine으로 진행되므로 코드가 사용자의 컴퓨터에서 로컬로 실행될 수 있습니다. 현재 코드는 sge를 사용하여 예외를 발견 할 때 로컬 가져 오기라는 의미에서 예상대로 작동하지만 여전히 더 강력하게 만들기 위해 여기에서 예외 처리를 개선하려고합니다.

내 의견으로는 stdout에 인쇄 된 실제 예외 메시지를 갖는 것이 좋은 이유는 사용자가 sge_execution_engine을 가져올 수없는 이유를 알 수 있기 때문입니다. 특히 가져 오기에 실패 할 것으로 기대하지 않는 경우에 특히 그렇습니다. 대신 실제로 실제 예외 메시지가 화면에 인쇄하도록 print sys.exc_info()를 사용

그러나, 나는 아마 더 좋은 방법은 except EXCEPTION as some_variable_name 형식을 사용하고 print some_variable_name을 인쇄하고도 관련 지을 수 있었던 속성의 일부를 호출하는 것입니다 것을 깨달았다 던져진 예외는 some_variable_name에게 배정됩니다.

나는이 코드의 덩어리 있었던 Python tutorial on exceptions에서 수행되는 본 다음 except IOError as e 덩어리가 구체적으로 errno에 호출하여 세밀한 방법으로 예외 메시지를 처리하는 것처럼

import sys 

try: 
    f = open('myfile.txt') 
    s = f.readline() 
    i = int(s.strip()) 
except IOError as e: 
    print "I/O error({0}): {1}".format(e.errno, e.strerror) 
except ValueError: 
    print "Could not convert data to an integer." 
except: 
    print "Unexpected error:", sys.exc_info()[0] 
    raise 

보인다 IOError 개체의 strerror 특성 그러나 IOErrordocumentation을 보면 예외에 대한 설명서의 일부로 나열된 특정 특성이 표시되지 않습니다. 사실, 이것은 파이썬 문서에있는 다른 모든 예외에서도 마찬가지입니다. 따라서 특정 예외와 관련된 속성이 무엇인지 파악할 수있는 방법이없는 것처럼 보입니다. 이에 대해 전혀 알지 못하면 import EXCEPTION as some_variable_name 구문을 사용하여 예외를 처리 할 때 some_variable_name 개체에서 호출 할 특성을 파악할 수있는 방법은 무엇입니까?

아무에게도 제안을 해주시고 답이 직접 내 질문에 답하지 않더라도 내 예외를 어떻게 처리 할 수 ​​있는지에 대한 완전히 다른 제안이 있으시면 주저하지 마시고 게시하다!

대단히 감사합니다!

답변

0

먼저 예외를 무시하고 변수를 무시한 다음 다시 sys.exc_info()으로 꺼내는 것이 좋습니다. exc_info을 사용하는 데는 몇 가지 좋은 이유가 있습니다 (저수준 코드, 2.6 이전 및 3.x와 모두 작동해야하는 코드 등).) 일반적으로, 당신이 그것을 할 수있을 때, 당신은해야합니다.

그리고이 기능은 마지막으로 제외 된 경우에도 작동합니다. 2.7에서 일반 except:except Exception:과 같은 의미이므로 except Exception as e:으로 쓸 수 있으며 e 값을 사용할 수 있습니다.

여러 예외 유형에 대해 똑같은 작업을 수행하려는 경우 except (RuntimeError, ImportError) as e:을 쓸 수 있습니다.

"더욱 견고하게"한다는 것은 절대적인 것이 아닙니다. 예를 들어, RuntimeError이나 ImportError이 아닌 예기치 않은 예외가있는 경우 로그에 기록하고 대체 코드를 시도 하시겠습니까, 아니면 추적 코드를 덤프 하시겠습니까? 예를 들어 프로그램에 나쁜 수정 사항을 체크인 한 사람이 원인 인 SyntaxError 인 경우 런타임 오류처럼 처리하고 싶지 않을 수도 있고 그렇지 않을 수도 있습니다. 이는 실제로 개발 관행과 대상 사용자 기반에 달려 있습니다.


한편 다음 except IOError as e 덩어리가 특히 IOError 개체의 errnostrerror 속성을 호출하여 세밀한 방법으로 예외 메시지를 처리하는 것처럼

보인다. 그러나 IOError documentation을 보면 예외에 대한 설명서의 일부로 나열된 이러한 특정 특성이 표시되지 않습니다.

hierarchy을 찾아야합니다. IOErrorEnvironmentError의 하위 클래스이며 errnostrerror 특성을 설명합니다. (이러한 특성은 실제로 OSError와 그 서브 클래스에 대한 documneted하지만, 그들이 존재한다는 사실이 설명되어 있습니다 무엇을 의미.)

이 엉망의 모든 조금 생각한다면 ... 글쎄, 그것은이다. 이 모든 것은 Python 3.x에서 정리되었습니다. IOErrorEnvironmentErrorOSError으로 병합됩니다. 그 속성은 명확하게 문서화되어 있으며, 보통 errno을 켜기 위해 일반적으로 errno 값이 다음과 같은 특정 서브 클래스를 생성하기 때문에 전환 할 필요가 없습니다. FileNotFoundError 등이 있습니다. 그러나 2.7을 사용하는 한, 언어에 대한 지난 6 년간의 개선의 이점을 얻지 못합니다. 계층 구조 또는 ValueError=>StandardError=>Exception (최저에서 계층 구조의 최상위에)보고 예를 들어


는, 나는 그것에 대해 어떤 속성을 찾을 수 없습니다. argsmessage :

당신 dirValueError 경우에만 (__repr____class_ 같은 보통 특별한 물건 외에) 두 가지 속성을 가지고 있음을 볼 수 있습니다.

message은 2.5에서 더 이상 사용되지 않으며 2.7 이전의 일부 코드 만 실행되도록 허용하기 때문에 문서화되지 않았습니다.* 그러나 args이 문서화되어 있습니다. 당신은 단지 BaseException에, 한 단계 더 올라갈해야합니다

args

예외 생성자에 지정된 인수의 튜플. 일부 기본 제공 예외 (예 : IOError)는 특정 개수의 인수를 예상하고이 튜플의 요소에 특별한 의미를 할당하는 반면, 다른 튜플은 일반적으로 오류 메시지를 제공하는 단일 문자열로만 호출됩니다.

ValueError에서 다른 속성을 찾을 수없는 이유는 찾을 수있는 다른 속성이 없다는 것입니다. 그리고 다른 클래스들도 마찬가지입니다. 특별한 속성을 (OSError은, SyntaxError은, 아마 다른 곳에서 다음 stdlib에 몇 가지 모듈 별 유형)을 명시 적으로 문서화이 유형의 소수입니다. **

우리가 except some_exception as e 구문을 사용하는 경우 print e 충분한을하고있다 그 속성을 호출하지 않고 인쇄 예외를 얻을

에게 인쇄 예외의 일부 유용한 형태를 얻기에 충분합니다. 다시, BaseException 문서에서 : 인수가 없었다 때이 클래스의 인스턴스에서 호출 str() 또는 unicode() 경우

는 인스턴스에 인수 (들)의 표현은 빈 문자열이 반환이나된다.

어떤 경우에는 원하는 것이 아닙니다. 특히 예외의 유형은 포함되지 않습니다. repr을 사용하면 생성자 호출 (예 : ValueError("invalid literal for int() with base 10: 'f'"))과 비슷한 모양을 얻을 수 있습니다. 당신이 추적에 들어갈 동일한 출력을 원하는 경우에

, 당신은 함께 자신-예 :., '{}: {}'.format(type(e), e)typestr 또는 unicode을 넣어해야합니다.

10 또는 그 문자열 'f'-well과 같이 예외가 아닌 실제 정보를 얻으려면 해당 정보가 이미 버려 졌기 때문에 *** 수 없습니다. 당신처럼, 그것을 추적하기 위해 자신의 코드를 작성해야합니다 :

try: 
    i = int(s, 16) 
except ValueError as e: 
    print '{} is not a base-16 number'.format(s) 

*이 그것입니다 self.args = tuple(args); self.message = str(args[0]) if args else ''을 위해 정의 된 BaseException.__init__(self, *args) 것처럼.

** ** 나는 2.5에서 CPython의 구현 세부 사항으로서 문서화되지 않은 속성을 갖고있는 예외 유형이 몇 개 있다고 생각하지만 2.7으로 모두 사라 졌거나 문서화되었다.

*** 글쎄, 당신은 예외 문자열을 구문 분석 할 수 있지만, 말할 필요도없이, 그 구현 세부 아니라 안정적인 호환성을 보장 뭔가. 자이 썬이나 스페인어 시스템에서 다를 수 있으며 예상대로 문자열을 인용하지 않을 수도 있습니다.베어 except를 사용

+0

도움 주셔서 감사합니다. 그러나 귀하의 제안에 따라 일부 예외에 대한 속성을 여전히 찾을 수 없습니다. 예를 들어, 계층 구조를 살펴 보거나 ValueError => StandardError => Exception (계층 구조에서 가장 낮은 것부터 가장 높은 것까지)에 대해서는 어떤 속성도 찾을 수 없습니다. 그리고이 예외를 제외하고, 이와 같은 예외도 있습니다. 그렇다면이 예외에 대해 어떤 속성을 호출해야하는지 어떻게 알 수 있습니까? 'except some_exception as e' 문법을 사용하고 있다면 (Pydocs에서했던 것처럼) 속성을 호출하지 않고 예외를 인쇄하기에 충분한'print e'를 수행하고 있습니까? – AKKO

+0

@AKKO : 대부분의 예외에는 '예외'에 정의 된'args'와'message' 속성 외에 표준 속성을 제외한 _any_ 속성이 없습니다. 자세한 내용으로 답변을 업데이트하겠습니다. – abarnert

0

거의 좋은 생각은 없지만,이 드문 시간 중 하나입니다 - 당신이 경우 어떤 이유로, 사용하려는 백업을 주로하기 때문에, 당신은 시스템 sge을 가져올 수 없습니다 :

try: 
    import sge_execution_engine as execution_engine 
except: 
    print "Use local execution engine because SGE support is missing!" 
    print sys.exc_info() # Print out the exception message 
    import local_execution_engine as execution_engine 

이제 except 절 하나만 필요합니다. 당신의 except에 다음

import logging 
logger = logging.getLogger() 
logger.setLevel(logging.WARNING) 

과 :

사용자에게 정보를 받고 처리하는 더 좋은 방법은 가서 그것을 밖으로 인쇄하고도 영구적 인 기록을 확인하기 위해 logging 모듈을 사용 아마도 조항 추가 :

logger.exception('unable to import sge') 

실제 메시지와 함께 메시지는 로그 파일에 저장됩니다.