[python] 파이썬에서 예외를 수동으로 발생 (throw)

파이썬에서 예외를 발생시켜 나중에 except블록을 통해 예외를 잡을 수 있습니까?



답변

파이썬에서 수동으로 예외를 발생 / 발생시키는 방법은 무엇입니까?

의미 상 문제에 맞는 가장 구체적인 Exception 생성자를 사용하십시오 .

메시지에 구체적으로 설명하십시오. 예 :

raise ValueError('A very specific bad thing happened.')

일반적인 예외를 제기하지 마십시오

일반을 올리지 마십시오 Exception. 그것을 잡으려면 그것을 서브 클래스 화하는 다른 모든 더 구체적인 예외를 잡아야합니다.

문제 1 : 버그 숨기기

raise Exception('I know Python!') # Don't! If you catch, likely to hide bugs.

예를 들면 다음과 같습니다.

def demo_bad_catch():
    try:
        raise ValueError('Represents a hidden bug, do not catch this')
        raise Exception('This is the exception you expect to handle')
    except Exception as error:
        print('Caught this error: ' + repr(error))

>>> demo_bad_catch()
Caught this error: ValueError('Represents a hidden bug, do not catch this',)

문제 2 : 잡을 수 없습니다

그리고 더 구체적인 캐치는 일반적인 예외를 포착하지 못합니다.

def demo_no_catch():
    try:
        raise Exception('general exceptions not caught by specific handling')
    except ValueError as e:
        print('we will not catch exception: Exception')


>>> demo_no_catch()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in demo_no_catch
Exception: general exceptions not caught by specific handling

모범 사례 : raise진술

대신, 의미 상 문제에 맞는 가장 구체적인 Exception 생성자를 사용하십시오 .

raise ValueError('A very specific bad thing happened')

또한 임의의 수의 인수를 생성자에게 전달할 수 있습니다.

raise ValueError('A very specific bad thing happened', 'foo', 'bar', 'baz') 

이러한 인수는 객체 의 args속성에 의해 액세스됩니다 Exception. 예를 들면 다음과 같습니다.

try:
    some_code_that_may_raise_our_value_error()
except ValueError as err:
    print(err.args)

인쇄물

('message', 'foo', 'bar', 'baz')    

Python 2.5에서는 실제 message속성이 추가되어 BaseException사용자가 예외를 서브 클래스 화하고 사용을 중지하도록 권장 args했지만 arg 의 도입 message및 원래 사용 중단이 취소되었습니다 .

모범 사례 : except조항

예를 들어 except 절 안에있을 때 특정 유형의 오류가 발생했음을 기록한 다음 다시 발생 시키려고 할 수 있습니다. 스택 추적을 유지하면서이를 수행하는 가장 좋은 방법은 bare raise 문을 사용하는 것입니다. 예를 들면 다음과 같습니다.

logger = logging.getLogger(__name__)

try:
    do_something_in_app_that_breaks_easily()
except AppError as error:
    logger.error(error)
    raise                 # just this!
    # raise AppError      # Don't do this, you'll lose the stack trace!

오류를 수정하지 말고 고집하십시오.

당신과 함께 스택 트레이스 (및 오류 값)을 보존 할 수 sys.exc_info()있지만, 이 방법이 더 오류가 발생하기 쉬운입니다파이썬 2와 3 사이의 호환성 문제가 베어를 사용하는 것을 선호 raise다시 인상 할 수 있습니다.

설명- sys.exc_info()유형, 값 및 역 추적을 리턴합니다.

type, value, traceback = sys.exc_info()

이것은 Python 2의 구문입니다. 이는 Python 3과 호환되지 않습니다.

    raise AppError, error, sys.exc_info()[2] # avoid this.
    # Equivalently, as error *is* the second object:
    raise sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]

원하는 경우 새로운 인상으로 발생하는 상황을 수정할 수 있습니다 ( args예 : 인스턴스에 대해 새로운 설정) .

def error():
    raise ValueError('oops!')

def catch_error_modify_message():
    try:
        error()
    except ValueError:
        error_type, error_instance, traceback = sys.exc_info()
        error_instance.args = (error_instance.args[0] + ' <modification>',)
        raise error_type, error_instance, traceback

그리고 우리는 인수를 수정하면서 전체 역 추적을 유지했습니다. 이것은 모범 사례아니며 Python 3에서는 유효하지 않은 구문 이므로 호환성을 유지하기가 훨씬 어려워집니다.

>>> catch_error_modify_message()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in catch_error_modify_message
  File "<stdin>", line 2, in error
ValueError: oops! <modification>

에서 파이썬 3 :

    raise error.with_traceback(sys.exc_info()[2])

다시 : 수동으로 추적을 조작하지 마십시오. 효율성떨어지고 오류가 발생하기 쉽습니다. 그리고 스레딩을 사용하고 sys.exc_info있고 잘못된 역 추적을 얻는 경우 (특히 제어 흐름에 대해 예외 처리를 사용하는 경우 개인적으로 피하는 경향이 있습니다.)

파이썬 3, 예외 체인

Python 3에서는 예외를 연결하여 트레이스 백을 보존 할 수 있습니다.

    raise RuntimeError('specific message') from error

알아 두십시오 :

  • 않는 오류 유형 제기 변경 허용하고,
  • 이것은 Python 2와 호환 되지 않습니다 .

더 이상 사용되지 않는 방법 :

이것들은 쉽게 생산 코드에 숨기거나 들어갈 수 있습니다. 예외를 제기하고 싶을 때 예외가 발생 하지만 의도 한 예외는 발생 하지 않습니다!

Python 2에서는 유효하지만 Python 3에서는 유효하지 않습니다 .

raise ValueError, 'message' # Don't do this, it's deprecated!

이전 버전의 Python (2.4 이하) 에서만 유효 하지만 여전히 문자열을 올리는 사람들이 있습니다.

raise 'message' # really really wrong. don't do this.

모든 최신 버전에서 유형을 TypeError올리지 않기 때문에 실제로을 올립니다 BaseException. 올바른 예외를 확인하지 않고 문제를 알고있는 검토자가없는 경우 프로덕션에 들어갈 수 있습니다.

사용법 예

소비자가 API를 잘못 사용하는 경우 소비자에게 경고하기 위해 예외를 제기합니다.

def api_func(foo):
    '''foo should be either 'baz' or 'bar'. returns something very useful.'''
    if foo not in _ALLOWED_ARGS:
        raise ValueError('{foo} wrong, use "baz" or "bar"'.format(foo=repr(foo)))

제안 할 때 고유 한 오류 유형 만들기

“의도에 들어가기 위해 의도적으로 오류를 만들고 싶습니다.”

응용 프로그램에 특정한 문제가 있음을 나타내려면 고유 한 오류 유형을 만들 수 있습니다. 예외 계층 구조에서 해당 지점을 하위 클래스로 지정하면됩니다.

class MyAppLookupError(LookupError):
    '''raise this when there's a lookup error for my app'''

그리고 사용법 :

if important_key not in resource_dict and not ok_to_be_missing:
    raise MyAppLookupError('resource is missing, and that is not ok.')


답변

이 작업을 수행하지 마십시오 . 베어를 올리는 Exception것이 절대적으로 옳은 일이 아닙니다 . 대신 Aaron Hall의 훌륭한 답변을 참조하십시오 .

이보다 더 많은 파이썬을 얻을 수는 없습니다.

raise Exception("I know python!")

더 많은 정보를 원하시면 파이썬에 대한 raise 문 문서 를 참조하십시오 .


답변

Python3에는 예외 예외에 대한 4 가지 구문이 있습니다.

1. raise exception
2. raise exception (args)
3. raise
4. raise exception (args) from original_exception

1. 예외 제기 vs. 예외 제기 (args)

raise exception (args) 예외를 발생시키는 데 사용 하는 경우 args아래 예와 같이 예외 개체를 인쇄 할 때 예외가 인쇄됩니다.

  #raise exception (args)
    try:
        raise ValueError("I have raised an Exception")
    except ValueError as exp:
        print ("Error", exp)     # Output -> Error I have raised an Exception 



  #raise execption 
    try:
        raise ValueError
    except ValueError as exp:
        print ("Error", exp)     # Output -> Error 

3. 인상

raise인수가없는 진술은 마지막 예외를 다시 발생시킵니다. 이는 예외를 포착 한 후 일부 조치를 수행 한 후 다시 발생시키려는 경우에 유용합니다. 그러나 이전에 예외가 없었 으면 raisestatement는 TypeErrorException을 발생시킵니다.

def somefunction():
    print("some cleaning")

a=10
b=0
result=None

try:
    result=a/b
    print(result)

except Exception:            #Output ->
    somefunction()           #some cleaning
    raise                    #Traceback (most recent call last):
                             #File "python", line 8, in <module>
                             #ZeroDivisionError: division by zero

4. original_exception에서 예외 (args)를 발생시킵니다.

이 명령문은 다른 예외에 대한 응답으로 발생한 예외에 아래 예에 표시된대로 원래 예외의 세부 사항을 포함 할 수있는 예외 체인을 작성하는 데 사용됩니다.

class MyCustomException(Exception):
pass

a=10
b=0
reuslt=None
try:
    try:
        result=a/b

    except ZeroDivisionError as exp:
        print("ZeroDivisionError -- ",exp)
        raise MyCustomException("Zero Division ") from exp

except MyCustomException as exp:
        print("MyException",exp)
        print(exp.__cause__)

산출:

ZeroDivisionError --  division by zero
MyException Zero Division
division by zero


답변

예상치 못한 조건에 대한 응답으로 예외를 throw해야하는 예외적 인 상황에서 포착하려는 의도는 없지만, 발생하는 경우 디버깅을 할 수 있도록 빠르게 실패하는 경우가 가장 많습니다. AssertionError:

if 0 < distance <= RADIUS:
    #Do something.
elif RADIUS < distance:
    #Do something.
else:
    raise AssertionError("Unexpected value of 'distance'!", distance)


답변

기존 답변을 먼저 읽으십시오. 이것은 단지 부록입니다.

인수를 사용하거나 사용하지 않고 예외를 발생시킬 수 있습니다.

예:

raise SystemExit

프로그램을 종료하지만 무슨 일이 있었는지 알고 싶을 수도 있습니다.

raise SystemExit("program exited")

프로그램을 닫기 전에 “프로그램 종료”를 stderr에 인쇄합니다.


답변

예외를 던지는 또 다른 방법은 assert입니다. assert를 사용하여 조건이 충족되지 않은 경우 조건이 충족되는지 확인할 수 있습니다 AssertionError. 자세한 내용은 여기 를 참조 하십시오 .

def avg(marks):
    assert len(marks) != 0,"List is empty."
    return sum(marks)/len(marks)

mark2 = [55,88,78,90,79]
print("Average of mark2:",avg(mark2))

mark1 = []
print("Average of mark1:",avg(mark1))


답변

참고 사항 : 일반적인 예외를 처리하고 싶을 때가 있습니다. 많은 파일을 처리하고 오류를 기록하는 경우 파일에 발생하는 모든 오류를 포착하고 기록한 다음 나머지 파일을 계속 처리 할 수 ​​있습니다. 이 경우

try:
    foo()
except Exception as e:
    print(str(e)) # Print out handled error

좋은 방법을 차단하십시오. 그래도 raise특정 예외를 원하므로 그 의미를 알 수 있습니다.