파이썬 튜토리얼 7장 오류와 이상

10530 단어
이 시리즈의 문장은 내가 파이톤을 배우는 것이다.9의 공식tutorial의 노트는 대부분이 홈페이지의 중국어 번역에서 유래한 것이다. 그러나 이 번역의 일부 부분은 너무 나쁘고 수다스러워서 저는 삭제와 수정을 많이 했고 일부 원문이 이해하지 못하는 부분도 있습니다. 저는 다른 자료를 참고하여 설명을 추가했습니다.
7.1 문법 오류
구문 오류를 구문 분석 오류라고도 합니다.
>>> while True print('Hello world')
  File "", line 1
    while True print('Hello world')
                   ^
SyntaxError: invalid syntax

7.2 이상
비록 문장이나 표현식이 문법적으로 정확하지만, 실행을 시도할 때, 그것은 여전히 오류를 일으킬 수 있다.실행할 때 검출되는 오류를 이상이라고 하는데, 이상이 반드시 심각한 결과를 초래하는 것은 아니다.그러나 대부분의 예외는 프로그램에서 처리되지 않으며 다음과 같은 오류 메시지가 표시됩니다.
>>> 10 * (1/0)
Traceback (most recent call last):
  File "", line 1, in 
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
  File "", line 1, in 
TypeError: Can't convert 'int' object to str implicitly

상기 예시 중의 이상 유형은 ZeroDivisionError,NameErrorTypeError 순이다.이상 형식으로 인쇄된 문자열은 내장된 이상 이름입니다.내장 이상은 내장 이상과 그 의미를 보여 줍니다.
7.3 예외 처리
선택한 이상을 처리하는 프로그램을 작성할 수 있습니다.다음 예를 보십시오. 유효한 정수를 입력할 때까지 입력해야 하지만, 프로그램을 중단할 수 있습니다. (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 자구(tryexcept 키워드 사이의 (여러 줄) 문구를 실행합니다.
  • 이상이 발생하지 않으면 except 서브문장을 건너뛰고 try 문장의 실행을 완성합니다.
  • try 자구를 실행할 때 이상이 발생하면 이 자구의 나머지 부분을 건너뜁니다.그리고 이상 유형이 except 키워드 뒤의 이상과 일치하면 except 자구를 실행하고 try 문장 뒤의 코드를 계속 실행합니다.
  • 발생한 이상이 except 서브문장에 지정된 이상과 일치하지 않으면 외부try 문장에 전달한다.처리 프로그램을 찾지 못하면, 처리되지 않은 이상입니다. 실행이 정지되고 위와 같은 메시지가 표시됩니다.하나의 try 문장에는 여러 개의 except 자구가 있을 수 있으며, 서로 다른 이상 처리 프로그램을 지정할 수 있습니다.최대 하나의 프로세서가 실행됩니다.하나의 except 자구는 여러 개의 이상을 괄호가 있는 원조로 명명할 수 있다. 예를 들어
  • ... except (RuntimeError, TypeError, NameError):
    ...     pass
    

    만약 발생한 이상과 except 자구의 클래스가 같은 클래스 또는 그 기본 클래스라면 이상은 except 자구의 클래스와 호환됩니다.예를 들어, 다음 코드는 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")
    

    만약 except 자구가 뒤바뀌면 (except B를 첫 번째로 놓으면) B, B, B 를 인쇄합니다. 즉, 첫 번째 일치하는 except 자구가 터치됩니다.마지막 except 자구는 어댑터로 사용할 이상 이름을 생략할 수 있습니다.그러나 이런 방식으로는 진정한 프로그래밍 오류를 감추기 쉽기 때문에 조심스럽게 사용하십시오.또한 오류 메시지를 인쇄한 다음 다시 예외를 일으키는 데 사용됩니다(호출자가 예외를 처리할 수 있음).
    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:
        print("Unexpected error:", sys.exc_info()[0])
        raise
    
    try ... except 문장에는 선택할 수 있는else 자구가 있는데 사용할 때 모든 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에 포착되는 것을 피하기 때문이다. 왜냐하면 보통 except가 포획하는 것은 그 안의 주요 논리이기 때문이다.
    except 자구는 이상 이름 뒤에 변수를 지정할 수 있습니다.이 변수는 이상 실례와 연결되어 있으며, 이상 생성된 매개 변수는 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)
    ...
    
    ('spam', 'eggs')
    ('spam', 'eggs')
    x = spam
    y = eggs
    

    7.4 이상 던지기raise 문장은 프로그래머가 지정한 이상을 강제로 발생하도록 허용한다.예를 들면 다음과 같습니다.
    >>> raise NameError('HiThere')
    Traceback (most recent call last):
      File "", line 1, in 
    NameError: HiThere
    
    raise 유일한 매개 변수는 던질 이상이다.이 매개 변수는 이상 실례나 이상 클래스 Exception 에서 파생된 클래스여야 합니다.예외 클래스가 전달되면 매개변수가 없는 구조 함수를 호출하여 암시적으로 인스턴스화합니다.
    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 "", line 2, in 
    NameError: HiThere
    

    7.5 이상 체인raise문장은 from로 이상 체인을 열 수 있습니다.예를 들면 다음과 같습니다.
    # exc must be exception instance or None.
    raise RuntimeError from exc
    

    이것은 네가 이상을 전환할 때 매우 유용하다.예를 들면 다음과 같습니다.
    >>> def func():
    ...     raise IOError
    ...
    >>> try:
    ...     func()
    ... except IOError as exc:
    ...     raise RuntimeError('Failed to open database') from exc
    ...
    Traceback (most recent call last):
      File "", line 2, in 
      File "", line 2, in func
    OSError
    
    The above exception was the direct cause of the following exception:
    
    Traceback (most recent call last):
      File "", line 4, in 
    RuntimeError: Failed to open database
    
    exceptfinally 자구에서 이상 체인은 자동으로 터치되므로 from None를 사용하여 이상 체인을 막을 수 있다.
    >>> try:
    ...     open('database.sqlite')
    ... except IOError:
    ...     raise RuntimeError from None
    ... 
    Traceback (most recent call last):
      File "", line 4, in 
    RuntimeError
    

    더 자세한 내용은 내장된 이상을 보십시오.
    7.6 사용자 정의 예외
    프로그램은 새로운 이상 클래스를 만들어서 자신들의 이상을 명명할 수 있습니다.이상은 통상적으로 Exception류에서 직접 또는 간접적으로 파생되어야 한다.여러 개의 오류가 발생할 수 있는 모듈을 만들 때 일반적으로 이 모듈에 정의된 이상에 대한 기본 클래스를 만들고 서로 다른 오류 조건에 대해 특정한 이상 클래스의 하위 클래스를 만듭니다.
    class Error(Exception):
        """Base class for exceptions in this module."""
        pass
    
    class InputError(Error):
        """Exception raised for errors in the input.
    
        Attributes:
            expression -- input expression in which the error occurred
            message -- explanation of the error
        """
    
        def __init__(self, expression, message):
            self.expression = expression
            self.message = message
    
    class TransitionError(Error):
        """Raised when an operation attempts a state transition that's not
        allowed.
    
        Attributes:
            previous -- state at beginning of transition
            next -- attempted new state
            message -- explanation of why the specific transition is not allowed
        """
    
        def __init__(self, previous, next, message):
            self.previous = previous
            self.next = next
            self.message = message
    

    대부분의 예외는 이름이 "Error"로 끝나는 것으로 정의되며 표준 예외의 이름과 유사합니다.
    7.7 정리 작업 정의try 문장에는 모든 상황에서 실행해야 하는 청소 작업을 정의하는 또 다른 선택할 수 있는 자구finally가 있습니다.예를 들면 다음과 같습니다.
    >>> try:
    ...     raise KeyboardInterrupt
    ... finally:
    ...     print('Goodbye, world!')
    ...
    Goodbye, world!
    KeyboardInterrupt
    Traceback (most recent call last):
      File "", line 2, in 
    
    finally 자구가 존재하면 finally 자구는 try 문구가 끝나기 전의 마지막 임무로 수행됩니다.finally 자구는 try 문구에 이상이 생겼든 없든 집행된다.다음은 예외가 발생했을 때 더 복잡한 몇 가지 상황에 대해 설명합니다.
  • 만약에 집행try 자구에 이상이 발생하면 이 이상은 하나except 자구에서 처리할 수 있다.만약 이상이 어떤 except 자구에 처리되지 않았다면 이 이상은 finally 자구가 집행된 후에 다시 발생할 것이다.
  • 이상도 except 또는 else 자구 집행 기간에 발생할 수 있다.마찬가지로 이 이상은 finally 자구가 집행된 후에 다시 발생한다.
  • 문장을 실행할 때 try 문장break, continue 또는 return 문장을 만나면 finally 자문은 집행break, continue 또는 return 문장 이전에 집행된다.
  • 만약에 finally 자구에 return 문구가 포함된다면 되돌아오는 값은 finally 자구의 어느 return 문구에서 되돌아오는 값이 아니라 try 문구에서 되돌아오는 값이다.예:
  • >>> 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 "", line 1, in 
      File "", line 3, in divide
    TypeError: unsupported operand type(s) for /: 'str' and 'str'
    

    실제 응용 프로그램에서 return 자구는 자원을 성공적으로 사용하든 안 하든 외부 자원(예를 들어 파일이나 네트워크 연결)을 방출하는 데 매우 유용하다.

    좋은 웹페이지 즐겨찾기