파이썬에서 예외를 발생시켜 나중에 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
인수가없는 진술은 마지막 예외를 다시 발생시킵니다. 이는 예외를 포착 한 후 일부 조치를 수행 한 후 다시 발생시키려는 경우에 유용합니다. 그러나 이전에 예외가 없었 으면 raise
statement는 TypeError
Exception을 발생시킵니다.
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
특정 예외를 원하므로 그 의미를 알 수 있습니다.