오류 메시지는 두 종류의 오류 즉, 구문 오류  예외가 있습니다

8.1. 구문 오류 

구문 분석 오류라고도 하는 구문 오류는 Python을 다루는 동안 발생하는 가장 일반적인 유형입니다.

>>>
while True print('Hello world')

  File "hello.py", line 1
    while True print('Hello world')
               ^^^^^
SyntaxError: invalid syntax

파서는 문제가 되는 줄을 감지하고 오류를 가리키는 작은 '화살표'를 표시합니다. 오류는 화살표 앞 의 토큰에 의해 발생합니다(또는 적어도 감지됨). 예제에서 오류는 while 구문에 콜론( ':')이 없기 때문에 오류가 감지됩니다 . 파일 이름과 줄 번호가 출력되어 어디를 봐야 하는지 알 수 있습니다.

8.2. Exceptions

문장이나 표현이 문법적으로 올바르더라도 실행을 면 오류가 발생할 수 있습니다. 실행 중에 감지된 오류를 예외 라고 합니다. 대부분의 예외는 프로그램에서 처리되지 않으며 다음과 같은 오류 메시지가 표시됩니다.

>>>
>>> 10 * (1/0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can only concatenate str (not "int") to str

오류 메시지의 마지막 줄은 무슨 일이 일어났는지 나타냅니다. 예외는 다양한 유형으로 제공되며 유형은 메시지의 일부로 출력됩니다. 예제의 유형은 ZeroDivisionErrorNameError및 TypeError입니다. 예외 유형으로 인쇄된 문자열은 발생한 내장 예외의 이름입니다. 표준 예외 이름은 기본 제공 식별자(예약 키워드 아님)입니다.

행의 나머지 부분은 예외 유형과 원인에 따라 세부 정보를 보여줍니다.

오류 메시지의 앞부분은 예외가 발생한 컨텍스트를 스택 역추적 형태로 보여줍니다. 일반적으로 소스 라인을 나열하는 스택 역추적을 포함합니다. 그러나 표준 입력에서 읽은 행은 표시하지 않습니다.

기본 제공 예외 는 기본 제공 예외와 해당 의미를 나열합니다.

8.3. 예외 처리 

선택된 예외를 처리하는 프로그램을 작성할 수 있습니다. 유효한 정수가 입력될 때까지 사용자에게 입력을 요청하지만 사용자가 프로그램을 중단할 수 있도록 허용하는 다음 예를 보십시오. 사용자 중단(Control-C)은 예외를 발생시켜 신호(KeyboardInterrupt)를 보냅니다.

Control-C  :  KeyboardInterrupt

>>>
while True:
     try:
         x = int(input("Please enter a number: "))
         break
     except ValueError:
         print("Oops!  That was no valid number.  Try again...")

try다음과 같이 문은 작동합니다.

  • 먼저 try 절 ( try및 except키워드 사이의 문 )이 실행됩니다.
  • 예외가 발생하지 않으면 예외 절 을 건너뛰고 try명령문의 실행 이 종료됩니다.
  • try절을 실행하는 동안 예외가 발생 하면 나머지 절은 건너뜁니다. 그런 다음 해당 유형이 except키워드 이름과 명명된 예외와 일치하면 예외 절이 실행되고 except 블록을 실행합니다.
  • 예외 절에 명명된 예외와 일치하지 않는 예외가 발생 하면 외부 try문으로 전달됩니다 . 핸들러가 발견 되지 않으면 처리되지 않은 예외 이며 위와 같은 메시지와 함께 실행이 중지됩니다.

try문은 하나 이상있을 수 있습니다. try절을 제외한 다른 예외 핸들러를 지정합니다. 최대 하나의 핸들러가 실행됩니다. 핸들러는 동일한 문의 다른 핸들러가 아닌 해당하는 try 절에서 발생하는 예외만 처리합니다. t괄호 안에 여러 예외를 지정할 수있습니다.

... except (RuntimeError, TypeError, NameError):
...     pass

다음 코드는 B, C, D를 순서대로 인쇄합니다.

class B(Exception):
    pass

class C(B):
    pass

class D(C):
    pass

for cls in [B, C, D]:
    try:
        raise cls()
    except D:
        print("D")
    except C:
        print("C")
    except B:
        print("B")

경우주의 조항을 제외하고는 (와 반전 된 첫번째)가 B, B, B를 인쇄 한 것 - 일치하는 첫 번째 절을 제외하고는 트리거됩니다.except B

모든 예외는 에서 상속 BaseException되므로 와일드카드로 사용할 수 있습니다. 이런 식으로 실제 프로그래밍 오류를 마스킹하기 쉽기 때문에 주의해서 사용하십시오! 또한 오류 메시지를 인쇄한 다음 예외를 다시 발생시키는 데 사용할 수도 있습니다(호출자도 예외를 처리할 수 있음).

import sys

try:
    f = open('myfile.txt')
    s = f.readline()
    i = int(s.strip())
except OSError as err:
    print("OS error: {0}".format(err))
except ValueError:
    print("Could not convert data to an integer.")
except BaseException as err:
    print(f"Unexpected {err=}, {type(err)=}")
    raise

또는 마지막 예외 절에서 예외 이름을 생략할 수 있지만 예외 값은 ys.exc_info()에서 검색해야 합니다.

try... except문은 선택이 다른 절 현재, 모두를 따라야합니다, except 절을 . try 절 에서 예외가 발생하지 않는 경우 실행해야 하는 코드에 유용합니다 . 예를 들어:

for arg in sys.argv[1:]:
    try:
        f = open(arg, 'r')
    except OSError:
        print('cannot open', arg)
    else:
        print(arg, 'has', len(f.readlines()), 'lines')
        f.close()

else절을 사용하면 try… except문 으로 보호되는 코드에 의해 발생하지 않은 예외를 실수로 catch하지 않는 경우를 예방합니다

예외가 발생하면 예외의 인수라고 하는 값이 있을 수 있습니다 . 인수의 존재와 유형은 예외 유형에 따라 다릅니다.

절을 제외하고는 예외 이름 뒤에 변수를 지정할 수 있습니다. 변수는 instance.args에 저장된 인수를 사용하여 예외 인스턴스에 바인딩됩니다. 편의를 위해 예외 인스턴스는 __str__()참조하지 않고도 인수를 직접 인쇄할 수 있도록 정의합니다 .args. 예외를 발생시키기 전에 먼저 예외를 인스턴스화하고 원하는 대로 속성을 추가할 수도 있습니다.

>>>
>>> try:
...     raise Exception('spam', 'eggs')
... except Exception as inst:
...     print(type(inst))    # the exception instance
...     print(inst.args)     # arguments stored in .args
...     print(inst)          # __str__ allows args to be printed directly,
...                          # but may be overridden in exception subclasses
...     x, y = inst.args     # unpack args
...     print('x =', x)
...     print('y =', y)
...
<class 'Exception'>
('spam', 'eggs')
('spam', 'eggs')
x = spam
y = eggs

예외에 인수가 있는 경우 처리되지 않은 예외에 대한 메시지의 마지막 부분('detail')으로 인쇄됩니다.

예외가 즉시 발생하는 경우 예외 핸들러는 예외를 처리하지 않는 시도 절 뿐만 아니라 그들이에서 (심지어 간접적으로)라고 내부 기능 발생하는 경우, 시도 절을 . 예를 들어:

>>>
>>> def this_fails():
...     x = 1/0
...
>>> try:
...     this_fails()
... except ZeroDivisionError as err:
...     print('Handling run-time error:', err)
...
Handling run-time error: division by zero

8.4. 예외 발생 

이 raise명령문을 사용하면 프로그래머가 지정된 예외가 발생하도록 강제할 수 있습니다. 예를 들어:

>>>
raise NameError('HiThere')

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: HiThere

유일한 인수는 발생할 raise예외 를 나타냅니다. 이것은 예외 인스턴스 또는 예외 클래스에서 파생된 클래스여야 합니다. 예외 클래스가 전달되면 인수 없이 생성자를 호출하여 암시적으로 인스턴스화됩니다.

raise ValueError  # shorthand for 'raise ValueError()'

예외가 발생했는지 여부를 확인해야 하지만 처리할 의사가 없는 경우 더 간단한 형식의 raise명령문을 사용하여 예외를 다시 발생시킬 수 있습니다.

>>>
try:
     raise NameError('HiThere')
except NameError:
     print('An exception flew by!')
     raise

An exception flew by!
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
NameError: HiThere

8.5. 예외 체이닝 

이 raise문 from은 연결 예외를 활성화 하는 선택 사항 을 허용합니다 . 예를 들어:

# exc must be exception instance or None.
raise RuntimeError from exc

이것은 예외를 변환할 때 유용할 수 있습니다. 예를 들어:

>>>
>>> def func():
...     raise ConnectionError
...
>>> try:
...     func()
... except ConnectionError as exc:
...     raise RuntimeError('Failed to open database') from exc
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "<stdin>", line 2, in func
ConnectionError

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
RuntimeError: Failed to open database

except또는 finally섹션 내에서 예외가 발생하면 예외 연결이 자동으로 발생합니다. .from None 관용구를 사용하여 비활성화할 수 있습니다 

>>>
>>> try:
...     open('database.sqlite')
... except OSError:
...     raise RuntimeError from None
...
Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
RuntimeError

연결 메커니즘에 대한 자세한 내용은 기본 제공 예외를 참조하세요 .

8.6. 사용자 정의 예외 

프로그램은 새로운 예외 클래스를 생성하여 자체 예외의 이름을 지정할 수 있습니다( Python 클래스에 대한 자세한 내용 은 클래스 참조 ). 예외는 일반적으로 Exception직접 또는 간접적으로 클래스에서 파생되어야 합니다 .

다른 클래스가 할 수 있는 모든 작업을 수행하는 예외 클래스를 정의할 수 있지만 일반적으로 단순하게 유지되며 종종 예외 처리기가 오류에 대한 정보를 추출할 수 있도록 하는 많은 속성만 제공합니다.

대부분의 예외는 표준 예외의 이름 지정과 유사하게 "오류"로 끝나는 이름으로 정의됩니다.

많은 표준 모듈은 정의한 기능에서 발생할 수 있는 오류를 보고하기 위해 자체 예외를 정의합니다. 

8.7. 정리 작업 정의 

try문은 모든 상황에서 실행해야합니다 청소 작업을 정의하기위한 것입니다. 예를 들어:

>>>
try:
     raise KeyboardInterrupt
finally:
     print('Goodbye, world!')

Goodbye, world!
KeyboardInterrupt
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>

finally절이 있는 경우 해당 절은 try문이 완료 되기 전에 마지막 작업으로 실행됩니다. 이 finally절은 try명령문이 예외를 생성하는지 여부에 관계없이 실행됩니다 . 다음 사항은 예외가 발생하는 더 복잡한 경우에 대해 설명합니다.

  • try 절 실행 중 예외가 발생하면 절에서 예외를 처리할 수 있습니다. 예외가 except 절에 의해 처리되지 않으면 finally 절이 실행 된 후 예외가 다시 발생합니다 .
  • except or else절을 실행하는 동안 예외가 발생할 수 있습니다 . 다시, finally절이 실행 된 후에 예외가 다시 발생합니다 .
  • if finally절이 실행될 때 breakcontinue또는 return문은 예외가 다시 발생하지 않습니다.
  • IF try문이 도달 breakcontinue또는 return문을의 finally절은 직전에 실행됩니다 .
  • finally절이 포함 return 문을 반환 값의 하나가 될 것입니다 finally조항의 return문이 아닌의 값 try조항의 return 문.

예를 들어:

>>>
>>> def bool_return():
...     try:
...         return True
...     finally:
...         return False
...
>>> bool_return()
False

더 복잡한 예:

>>>
>>> def divide(x, y):
...     try:
...         result = x / y
...     except ZeroDivisionError:
...         print("division by zero!")
...     else:
...         print("result is", result)
...     finally:
...         print("executing finally clause")
...
>>> divide(2, 1)
result is 2.0
executing finally clause
>>> divide(2, 0)
division by zero!
executing finally clause
>>> divide("2", "1")
executing finally clause
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in divide
TypeError: unsupported operand type(s) for /: 'str' and 'str'

보시다시피 finally절은 모든 이벤트에서 실행됩니다. TypeError개의 스트링을 분할함으로써 발생은 처리되지 except절과 후 따라서 레이즈 다시 finally 절 실행되었다.

실제 응용 프로그램에서 이 finally절은 리소스 사용의 성공 여부와 상관없이 외부 리소스(예: 파일 또는 네트워크 연결)를 해제하는 데 유용합니다.

8.8. 사전 정의된 정리 작업 

일부 개체는 개체를 사용한 작업의 성공 여부에 관계없이 개체가 더 이상 필요하지 않을 때 수행할 표준 정리 작업을 정의합니다. 파일을 열고 그 내용을 화면에 인쇄하려고 시도하는 다음 예를 보십시오.

for line in open("myfile.txt"):
    print(line, end="")

이 코드의 문제는 코드의 이 부분이 실행을 완료한 후 불확실한 시간 동안 파일을 열어 둡니다. 이것은 단순한 스크립트에서는 문제가 되지 않지만 더 큰 응용 프로그램에서는 문제가 될 수 있습니다. 이 with명령문을 사용하면 파일과 같은 개체를 항상 신속하고 정확하게 정리할 수 있는 방식으로 사용할 수 있습니다.

with open("myfile.txt") as f:
    for line in f:
        print(line, end="")

명령문이 실행된 후 파일 f 는 라인을 처리하는 동안 문제가 발생하더라도 항상 닫힙니다. 파일과 같이 미리 정의된 정리 작업을 제공하는 개체는 문서에서 이를 나타냅니다.

'Python' 카테고리의 다른 글

Python - Virtual Environments and Packages  (0) 2022.01.06
Python - 표준라이브러리 II  (0) 2022.01.06
Python - 입출력  (0) 2022.01.06
Python - module  (0) 2022.01.06
Python - class  (0) 2022.01.06

+ Recent posts