모든 예외 잡기


698

모든 예외를 잡는 try/ except블록을 어떻게 작성할 수 있습니까?


4
대부분의 경우 예외를 잡으려고하면 아마도 잘못된 일을하고있을 것입니다. 코드에서 철자를 잘못 입력해도 알 수 없을 것입니다. 특정 예외를 포착하는 것이 좋습니다.
vwvolodya 2014 년

12
더 정확하게 말하면 가능한 모든 예외를 포착하는 것은 자동으로 포착되는 경우에만 문제가됩니다. 발견 된 오류 메시지가 인쇄되고 sys.stderr기록 될 수 있는 곳 이외의 다른 접근 방법이 적절한 곳을 생각하기는 어렵습니다 . 그것은 완벽하게 유효하고 일반적인 예외입니다.
Evgeni Sergeev

당신은 시도 try: whatever() except Exception as e: exp_capture() 했습니까?
Charlie Parker

답변:


564

당신은 할 수 있지만 아마해서는 안됩니다 :

try:
    do_something()
except:
    print "Caught it!"

그러나 이것은 또한 예외를 잡을 것이고 KeyboardInterrupt일반적으로 원하지 않는 것입니까? 예외를 즉시 다시 발생 시키지 않으면 문서에서 다음 예제 참조하십시오 .

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


15
마지막 진술은 사실이 아니며 except Exception:BaseException도 포착한다는 점을 제외하고는 명시 적으로 드러내야합니다.
Pykler

7
실제로 stderr에 인쇄해야합니다.
nyuszika7h

41
나는 "하지 말아야한다"는 말에 매우 반대한다. 드물게해야합니다. 예외로 완전히 미쳐 버린 타사 라이브러리 (때로는 동적으로로드 된 !!)를 처리 할 때가 있습니다. 모두를 추적하는 것은 매우 고통스러운 일이 될 수 있습니다. 단 하나만 놓치면 매우 시스템에 큰 고통스러운 버그. 즉, 가능한 한 많은 수를 추적하고 적절하게 처리 한 다음 놓친 데이터를 모두 백업하는 것이 좋습니다.
Blaze

26
내가 이상하게 생각하는 것은 인스턴스 변수를 선언하지 않는 오리 타이핑 언어에서 모든 예외를 타이핑하지 않는 것에 대해 갑자기 매우 염려한다는 것입니다. 흠!
Blaze

839

베어 except:조항 (다른 사람들이 사용해서는 안된다고 말한 것) 외에도 다음을 간단히 잡을 수 있습니다 Exception.

import traceback
import logging

try:
    whatever()
except Exception as e:
    logging.error(traceback.format_exc())
    # Logs the error appropriately. 

예를 들어 종료하기 전에 포착되지 않은 예외를 처리하려는 경우 일반적으로 코드의 가장 바깥 레벨에서이 작업을 수행하는 것이 좋습니다.

의 장점 except Exception베어 이상은 except그것이 가장 분명 잡을 실 거예요 것을 몇 가지 예외가 있다는 것입니다 KeyboardInterrupt그리고 SystemExit당신이 잡은 그 다음 당신은 당신의 스크립트를 종료하는 사람을 위해 열심히 그것을 만들 수 삼키면 :.


나는 내 마음에 똑같은 것이 있었지만, 단점은 한 번 잡히면 두 가지 오류가 있다고 가정하고 인쇄를 제외하고는 try 블록에서 벗어나 두 번째 오류를 알 수 없습니다. .

6
궁금한 사람은 내 기대와는 달리 적어도 파이썬 2.x에서 int와 같은 예외가 아닌 서브 클래스를 잡을 수 있습니다.
Joseph Garvin

5
@JosephGarvin, 그것은 부정확하다. 즉, 이것은 서브 클래스가 아닌 "예외 없음"을 포착하지 않을 Exception것이다. int예외로 as를 발생 시키는 것은 불가능하며 , 그렇게하려고 시도하면 TypeError예외 가 발생하며, except Exception그러한 경우 에는 동봉 절에 의해 포착됩니다 . 반면에, 이전 스타일 클래스를 제기 할 수 없습니다 서브 클래스 않는 "비 예외"자격이 Exception-이는 것이다 베어에 의해 잡힐 except절하지만 하지 에 의해 except Exception절.
Yoel

4
이 블로그 항목 확인 @JosephGarvin : chris-lamb.co.uk/posts/no-one-expects-string-literal-exception , 나는이 일에 @Yoel과 함께 있어요 당신의 테스트는 단지 마스크TypeError
던컨

2
@CharlieParker 당신이 원하는 것이지만 대부분 그렇지 않으면 잡는 데 아무런 문제가 없습니다. 호출은 sys.exit()일반적으로 앱이 종료 될 것으로 예상하지만 SystemExit를 잡으면 종료되지 않음을 의미합니다. 마찬가지로 실행중인 스크립트 (Ctrl-break)에서 control-C를 누르면 오류가 발생하지 않고 계속 진행되지 않고 프로그램이 중지됩니다. 그러나 기존에 정리하기를 원한다면 둘 중 하나를 잡을 수 있습니다.
던컨

100

일반적인 예외를 처리하기 위해이 작업을 수행 할 수 있습니다

try:
    a = 2/0
except Exception as e:
    print e.__doc__
    print e.message

8
모든 예외의 기본 클래스가 BaseException이고 예외 클래스 제품군에없는 프로덕션 코드가 발생했기 때문에 모든 예외를 포착하지 못할 수 있습니다. 이에 대한 자세한 내용은 docs.python.org/3/library/… 를 참조하십시오 .
DDay

4
이것은 모든 예외를 잡는 것은 아닙니다.
Andy_A̷n̷d̷y̷

6
기술적으로는 시스템 종료가 아닌 모든 예외를 포착해야합니다. 문서에서 @DDay linked : " exception BaseException : 모든 내장 예외에 대한 기본 클래스. 사용자 정의 클래스에 의해 직접 상속되지 않습니다 ( 그러므로 예외 사용)." 이것을 무시하는 코드로 작업하거나 시스템 종료 예외를 포착 해야하는 경우가 아니라면 위의 내용을 사용하는 것이 좋습니다.
피터 Cassetta

@PeterCassetta 언제 시스템 종료 예외를 포착하고 싶습니까? 우리가 이것을 잡기를 원하지 않는 것이 일반적인 질문 인 것처럼 보이지만 그 이유를 이해하지 못합니다. 보통은 어떻습니까?
Charlie Parker

68

가능한 모든 예외를 잡으려면 catch BaseException . 예외 계층 구조의 맨 위에 있습니다.

파이썬 3 : https://docs.python.org/3.5/library/exceptions.html#exception-hierarchy

파이썬 2.7 : https://docs.python.org/2.7/library/exceptions.html#exception-hierarchy

try:
    something()
except BaseException as error:
    print('An exception occurred: {}'.format(error))

그러나 다른 사람들이 언급했듯이 일반적으로 특정 경우에만 필요하지 않습니다.


1
Ctrl-C를 누른 후 장기 실행 작업의 진행 상황을 저장하고 싶습니까?
BallpointBen

54

여기에있는 것과 비슷한 매우 간단한 예 :

http://docs.python.org/tutorial/errors.html#defining-clean-up-actions

모든 예외를 잡으려고 시도하는 경우 'print "예외를 던질 수있는 조치 수행'대신"try : "문에 모든 코드를 넣으십시오.

try:
    print "Performing an action which may throw an exception."
except Exception, error:
    print "An exception was thrown!"
    print str(error)
else:
    print "Everything looks great!"
finally:
    print "Finally is called directly after executing the try statement whether an exception is thrown or not."

위의 예에서 다음 순서로 출력이 표시됩니다.

1) 예외가 발생할 수있는 조치 수행

2) 마지막으로 예외가 발생했는지 여부에 따라 try 문을 실행 한 직후에 호출됩니다.

3) "예외가 발생했습니다!" 또는 "모두 좋아 보인다!" 예외 발생 여부에 따라

도움이 되었기를 바랍니다!


26

특히 Python 3.0 이상에서 여러 가지 방법이 있습니다.

접근법 1

이것은 간단한 접근 방법이지만 실제로 어떤 코드 줄이 실제로 예외를 throw하는지 알 수 없으므로 권장되지 않습니다.

def bad_method():
    try:
        sqrt = 0**-1
    except Exception as e:
        print(e)

bad_method()

접근법 2

이 방법은 각 예외에 대한 자세한 정보를 제공하므로 권장됩니다. 다음을 포함합니다 :

  • 코드의 줄 번호
  • 파일 이름
  • 더 자세한 방법으로 실제 오류

유일한 단점은 tracback을 가져와야한다는 것입니다.

import traceback

def bad_method():
    try:
        sqrt = 0**-1
    except Exception:
        print(traceback.print_exc())

bad_method()

21

방금 Python 2.7에서 예외 이름이 있는지 테스트하기위한이 작은 트릭을 발견했습니다. 때로는 코드에서 특정 예외를 처리 했으므로 해당 이름이 처리 된 예외 목록에 있는지 확인하는 테스트가 필요했습니다.

try:
    raise IndexError #as test error
except Exception as e:
    excepName = type(e).__name__ # returns the name of the exception

2
try:
    whatever()
except:
    # this will catch any exception or error

이것이 적절한 파이썬 코딩이 아니라는 것을 언급 할 가치가 있습니다. 이것은 당신이 잡으려고하지 않을 많은 오류를 잡을 것입니다.


다른 답변에서 언급 한 모든 예외를 캐치하지 않는 것을 제외하고는 사용하십시오. 이 목적으로 BaseException을 사용해야하지만, 말한 것처럼 아무도 이와 같은 예외를 모두 잡아서는 안됩니다. 개발 중을 제외하고 더 세부적인 것을 추가하는 것이 목표라면
시작해도 괜찮을
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.