exception
- 뭐든 적당히 하다보면 보이는..
- 아무튼 예외처리
- 주요 키워드는
try,except,
else,finally가 있음 - 추가로
raise,with까지. 아무튼 기본 형식으로
1 2 3 4 5 6 7 8 9 10 11 12
try: ''' some statement''' except condition: ''' statement exception ''' except condition`: ''' statement exception ''' except condition``: ''' statement exception ''' else: ''' other exception ''' finally: ''' some statement '''
try
try~except사이 문장들 실행- exception이 없으면
except를 건너뜀 - exception이 있으면 그 블록의
뒤 코드는 건너뛰고
조건에 따라except실행
except
try에서 exception이 있고,
해당 유형이 명명되어 있으면
해당 블록 실행except만 쓰면 exception은 잡아주는데
구체적인 상황을 보려면
작업이 더 필요함 예를들어,1 2 3 4 5 6 7 8 9 10 11 12 13 14
import sys try: ''' some statement''' print(1) 1/0 except : print(sys.exc_info()) ''' statement exception ''' print(2) else: ''' other exception ''' print(3) finally: print(4)
1 2 3 4
1 (<class 'ZeroDivisionError'>, ZeroDivisionError('division by zero'), <traceback object at 0x0000013D4E508CC0>) 2 4
반대로, exception을 지정할 수 있고
선택적으로 alias를 줄 수도 있음.1 2 3 4 5 6 7
~ except Exception as e: print(e) print(e.with_traceback) ''' statement exception ''' print(2) ~
except만 쓸때랑 차이는
쓰기좀더 편하다는거?exception condition에 따라
처음 예시처럼 여러개가 올 수 있는데
실행은 하나만 됨
또는 조건을 묶어서 튜플로 쓸 수 있음1 2 3 4 5
~ except (FileExistsError, InterruptedError) as e: print(e) print(e.with_traceback) ~
- 명시된
except에 일치하는 exception이 아니면
외부 try로 전달됨.
else
else는 선택적으로 쓸 수 있는데
항상except뒤에 와야하며
try에서 exception이 없는 경우 실행.아래 case 1, case 2의 출력을 비교해보면
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
def mtd(num1, num2): res = num1 / num2 return res try: print(mtd(10, "asdf")) # case 1 # print(mtd(10,1)) # case 2 except ZeroDivisionError: print("Error: Cannot divide by zero") except TypeError as err: print("Error: Invalid type : {0}".format(err.args)) except: print("Error: Unknown error") else: print("No error") finally: print("Executed")
1 2 3 4 5 6 7 8 9
# case 1 Error: Invalid type : ("unsupported operand type(s) for /: 'int' and 'str'",) Executed # case 2 10.0 No error Executed
정상적인 경우 처리를 위해?
또
try에 코드를 추가하는 것보다
else의 사용을 권장하는듯한데,
except에 명시하지 않은 예외를
우연히 잡게 되는 것을 방지하기 위해서.라고 하는거 보면
try안에는
exception나올것만 하라는것같음
except를 명확하게 하라는 아무튼 그럼.
finally
try에서 exception에 상관없이 실행되는구간.try에서 발생한 exception이except에서
처리되지 않으면finally가 실행되고
exception다시 발생.1 2 3 4 5 6 7 8 9
try: print('start try') 10/'asdf' except ZeroDivisionError: print("Error") else: print("No error") finally: print("Executed")
1 2 3 4 5 6
start try Executed Traceback (most recent call last): File "F:\W\Python\test.py", line 31, in <module> 10/'asdf' TypeError: unsupported operand type(s) for /: 'int' and 'str'
except에 명시되지 않은 exception은
finally이후 발생.except,else에서 exception이 발생해도
finally를 실행하고 다시 exception발생.1 2 3 4 5 6 7 8 9 10
try: print('start try') 10/3 except ZeroDivisionError: print("Error") else: 10/'a' print("No error") finally: print("Executed")
1 2 3 4 5 6
start try Executed Traceback (most recent call last): File "F:\W\Python\test.py", line 35, in <module> 10/'a' TypeError: unsupported operand type(s) for /: 'int' and 'str'
else에 exception이 있어도
finally이후 exception 발생.finally에서break,continue를 실행하면
return exception이 발생하지 않음.try에서break,continue,return을 만나면,
finally는break,continue,return을
실행하기 직전에 실행.finally절에 return 이 포함되면,
reutrn값은try의 return 값이 아니라,
finally의 return 이 주는 값이 된다.1 2 3 4 5 6 7 8 9 10 11 12 13
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) divide(2, 0) divide("2", "1")
1 2 3 4 5 6 7 8 9 10 11
result is 2.0 executing finally clause division by zero! executing finally clause executing finally clause Traceback (most recent call last): File "F:\W\Python\test.py", line 56, in <module> divide("2", "1") File "F:\W\Python\test.py", line 42, in divide result = x / y TypeError: unsupported operand type(s) for /: 'str' and 'str'
- 아무튼 어떤 경우던간에
finally가
항상, 마지막에 실행된다는게 주요내용. try에서 외부 resource를 사용할 때,
exception상황에 관계없이
resource를 반납하는데 유용함.
파일 네트워크 등등.
raise
강제로 exception을 발생시킴
1
raise TypeError
1 2 3 4
Traceback (most recent call last): File "F:\W\Python\test.py", line 40, in <module> raise TypeError TypeError
custom exception
- class형태로 정의해 사용할 수 있음
- 보통 Error로 끝남.
보통 Exception을 상속.
1 2 3 4 5 6 7 8 9 10 11 12 13
class MyException(Exception): def __init__(self, value): self.value = value def __str__(self): return repr(self.value) try : for i in range(10): if i == 5: raise MyException(i) print(i) except MyException as e: print("MyException:", e.value)
1 2 3 4 5 6
0 1 2 3 4 MyException: 5
Exception을 상속하는게 아니면
1 2 3 4 5 6 7 8 9 10 11
def f(): print('in f') try: raise f() except Exception as e: print(e) else: print('no err') print('after try')
1 2 3
in f exceptions must derive from BaseException after try
실행은 어찌어찌되는것같은데
BaseException을 상속하라함
BaseException은 Exception바로 상위라그런듯?
with
- 일부(?) class는 객체가 필요 없을 때
스스로 resource를 정리함. - 객체사용의 성공여부는 상관없음.
finally가 항상 붙어있는형태.예를들어
1 2 3 4 5 6 7 8 9 10 11 12
f = open("text.txt", "r") print(f.closed) try: firstline = f.readline() print(firstline) except Exception as e: print(e) print(f.closed) print(f.closed) f.close() print(f.closed)
1 2 3 4 5 6 7 8
False 'cp949' codec can't decode byte 0xed in position 0: illegal multibyte sequence False False True # text.txt # 한글
text.txt파일에 한글이 써져있어서 Exception인 상황.
그래도 f.close하기 전까지 file은 열려있다.
이런 경우를 위함.with은 사용 후 resource가
정리되도록 보장함.1 2 3
with open("text.txt", "r", encoding='utf-8') as f: for line in f: print(line)
with블록 이후 어떤 경우에도 파일은 닫힘.여기저기 대충 요약해보면
1 2
with EXPR as VAR: BLOCK
이게 아래와 같음.
1 2 3 4 5 6
VAR = EXPR VAR.__enter__() try: BLOCK finally: VAR.__exit__()
근데
except가 없음.
exception은 따로처리해야함.그래서
with를 사용가능하게
class를 만들 수 있는데 예를들어1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
class CustomClass: def __init__(self, args): self.args = args def __enter__(self): # must return resource return self def use(self): print(self.args) def __exit__(self, type, value, traceback): self.arg = None with CustomClass("test") as cc: cc.use()
이거 알아서 잘 써먹으면됨.
class까지 귀찮으면
1 2 3 4 5 6 7 8 9 10
from contextlib import contextmanager @contextmanager def use(args): data = args yield data data = None with use('text') as u: print(u)
ㅇㅇ decorator.
위랑 같은 표현임.- 이부분은 더 설명이 많음.
필요하면 나중에.
Exception hierarchy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
BaseException
+-- SystemExit
+-- KeyboardInterrupt
+-- GeneratorExit
+-- Exception
+-- StopIteration
+-- StopAsyncIteration
+-- ArithmeticError
| +-- FloatingPointError
| +-- OverflowError
| +-- ZeroDivisionError
+-- AssertionError
+-- AttributeError
+-- BufferError
+-- EOFError
+-- ImportError
| +-- ModuleNotFoundError
+-- LookupError
| +-- IndexError
| +-- KeyError
+-- MemoryError
+-- NameError
| +-- UnboundLocalError
+-- OSError
| +-- BlockingIOError
| +-- ChildProcessError
| +-- ConnectionError
| | +-- BrokenPipeError
| | +-- ConnectionAbortedError
| | +-- ConnectionRefusedError
| | +-- ConnectionResetError
| +-- FileExistsError
| +-- FileNotFoundError
| +-- InterruptedError
| +-- IsADirectoryError
| +-- NotADirectoryError
| +-- PermissionError
| +-- ProcessLookupError
| +-- TimeoutError
+-- ReferenceError
+-- RuntimeError
| +-- NotImplementedError
| +-- RecursionError
+-- SyntaxError
| +-- IndentationError
| +-- TabError
+-- SystemError
+-- TypeError
+-- ValueError
| +-- UnicodeError
| +-- UnicodeDecodeError
| +-- UnicodeEncodeError
| +-- UnicodeTranslateError
+-- Warning
+-- DeprecationWarning
+-- PendingDeprecationWarning
+-- RuntimeWarning
+-- SyntaxWarning
+-- UserWarning
+-- FutureWarning
+-- ImportWarning
+-- UnicodeWarning
+-- BytesWarning
+-- EncodingWarning
+-- ResourceWarning
Comments powered by Disqus.