본문 바로가기

프로그래머/Python

[널널한 교수의 고급 파이썬] 04-2 with 구문과 컨텍스트 매니저

04-2 with 구문과 컨텍스트 매니저

try-except-else-finally 문

  • try
    • 먼저 try절이 실행되어 예외가 발생하지 않으면 except를 건너 뛰는데, 예외가 발생하면 오류를 확인하며 except의 매칭되는 부분으로 넘겨준다
  • except
    • try절에서 오류를 발생했을 때 처리할 내용을 담는다
  • else
    • try절에서 else는 에러가 발생하지 않을 때 실행하게 되는 블럭
  • finally
    • finally는 예외의 발생 여부와 상관 없이 항상 실행되는 블럭
def divide(x, y):
    try:
        result = x / y
    except ZeroDivisionError:
        print("0으로 나누는 오류발생")
    else:       # 예외가 발생하지 않을 경우 결과 출력
        print("결과: ", result)
    finally:    # 예외가 발생하던 안하던 항상 수행
        print("수행완료")

divide(100, 2)
divide(100, 0)

try-else 문

  • try 문에는 else 절을 사용할 수 있다
  • else 절은 예외가 발생하지 않은 경우에 실행되며 반드시 except 절 다음에 위치해야 한다

file을 읽어와서 data에 저장하는 기능

try:
    f = open('foo.txt', 'r')
except FileNotFoundError as e:
    print(str(e))
else:
    data = f.read()
    f.close()

try-finally

  • try 문에는 finally 절을 사용할 수 있다
  • finally 절은 try 문 수행도중 발생하는 예외에 관계 없이 항상 수행된다
  • 일반적으로 리소스를 오픈한 후 이를 close()하는 경우에 많이 사용된다

코드 가독성이 떨어짐

try:
    f = open("file.txt", "w")
    try:
        f.write('Hello World!')
    finally:
        f.close()
except IOError:
    print('oops!')

with 문

  • try/finally 구문을 더 간편하게 사용할 수 있다
  • content manager에 의해 실행되는 enter(), exit()을 정의하여 with 구문 body의 앞부분과 뒷부분 실행 코드를 대신할 수 있다
set things up
try:
    do something
finally:
    tear things down


class controlled_execution:
    def __enter__(self):
        set things up
        return thing
    def __exit__(self, type, value, traceback): 
        tear things down

with controlled_execution() as things:
    some code using thing

expression.enter() is bound to x, not the balue of expression

with expression as x:
    body

컨텍스트 매니저

  • with 문에서 사용하도록 설계된 객체

with 구문

  • with 구문이 실행되면 context manager가 자동적으로
    • enter() 메소드를 실행한다
    • 이 메소드가 반환하는 값이 as의 thing으로 저장된다
    • 그 후 some code using thing 에 해당하는 body 코드가 실행된다
  • 예외적인 상황이 생겨도 exit() 메소드는 호출이 보장된다

사례

  • 파이썬의 file 객체는 enter(), exit() 메소드가 구현되어 있다
  • 이 객체는 file object 자신을 반환한다
  • exit() 메소드는 당연히 파일을 close한다
import sys
f = open("x.txt")
f
f.__enter__() 
f.read(1)
f.__exit__()    # f.__exit__()에 의해 f.close()가 자동으로 실행
f.read(1)       # 따라서 f.read() 메소드는 오류 출력

# with 구문을 사용함으로써
# open()이 간단해지고, finally도 필요 없어졌다
with open("x.txt") as f:
    data = f.read()
    print(data)
try:
    f = open("file.txt", "w")
    try:
        f.write('Hello World!')
    finally:
        f.close()
except IOError:
    print('oops!')

# 좀 더 간결하고 효율적인 코드
try:
    with open("file.txt", "w") as outfile:
        outfile.write('Hello World!')
except IOError:
    print('oops!')