주제
컨텍스트 매니저에 대해 배웠다.
Context managers 사용하기
Context managers?
- 컨텍스트를 설정한다.
- 코드를 실행시킨다.
- 컨텍스트를 제거한다.
출장 뷔페로 예를 들면,
- 행사 시작 전, 직원들이 음식 세팅을한다.
- 행사 진행
- 행사 끝나면 음식 정리한다.
코드에서 예를 들면,
with open('my_file.txt') as my_file:
text = my_file.read()
length = len(text)
print('The file is {} characters long'.format(length))
여기서 open()
이 컨텍스트 관리자다.
- 파일을 열어 사용할 수 있도록 설정한다.
- 파일을 읽고 길이를 변수에 저장하는 작업을 수행한다.
- 파일이 닫혔는지 확인한다.
with
가 컨텍스트 매니저를 사용하겠다는 의미를 갖는다.
with 컨텍스트 매니저(인수..) as 반환된 값 할당할 변수 이름:
실행할 코드
정리 후 실행될 코드
연습문제
image = get_image_from_instagram()
# Time how long process_with_numpy(image) takes to run
with timer():
print('Numpy version')
process_with_numpy(image)
# Time how long process_with_pytorch(image) takes to run
with timer():
print('Pytorch version')
process_with_pytorch(image)
Numpy version
Processing..........done!
Elapsed: 1.52 seconds
Pytorch version
Processing..........done!
Elapsed: 0.33 seconds
컨텍스트 매니저 작성하기
컨텍스트 매니저를 만들 수도 있다.
- 클래스 기반
class File(object):
def __init__(self, file_name, method):
self.file_obj = open(file_name, method)
def __enter__(self):
return self.file_obj
def __exit__(self, type, value, trace_back):
self.file_obj.close()
with File('demo.txt', 'wb') as opened_file:
opened_file.wirte('Hola!')
- 함수 기반
@contextlib.contextmanager
def my_context():
컨텍스트에 필요한 설정 코드 추가 (옵션)
yield
컨텍스트 정리에 필요한 코드 추가 (옵션)
- 함수 정의
- 컨텍스트에 필요한 설정 코드 추가(옵션)
yield
키워드
- 컨텍스트 정리에 필요한 코드추가(옵션)
contextlib
패키지 사용해서 데코레이터 표시
yield 의미
쉽게 생각하면 return
과 유사하다.
import contextlib
@contextlib.contextmanager
def foo():
print("hi")
yield 1
print("bye")
with foo():
print("Zzz")
hi
Zzz
bye
import contextlib
@contextlib.contextmanager
def foo():
print("hi")
yield 1
print("bye")
with foo() as f:
print("Zzz")
print(f)
hi
Zzz
1
bye
중첩된 컨텍스트, 오류 처리 및 컨텍스트 매니저 생성 시기를 아는 방법에 대해 배워보자.
def copy(src, dst):
"""한 파일의 내용을 복사해서 다른 파일로 붙여넣는다.
Args:
src (str): 복사할 내용이 있는 파일
dst (str): 붙여넣을 새 파일
"""
with open(src) as f_src:
contents = f_src.read()
with open(dst, 'w') as f_dst:
f_dst.write(contents)
파일이 굉장히 크다면 다 읽을 때까지 기다려야한다. 중간에 뻗어버릴수도 있음...
이상적인 방법은 중첩 컨텍스트를 사용하는 것이다.
이 예제에서는 파일을 열고 한 줄씩 읽어서 바로바로 쓰도록 구현하는 것이 좋다.
def copy(src, dst):
"""한 파일의 내용을 복사해서 다른 파일로 붙여넣는다.
Args:
src (str): 복사할 내용이 있는 파일
dst (str): 붙여넣을 새 파일
"""
with open(src) as f_src:
with open(dst, 'w') as f_dst:
for line in f_src:
f_dst.write(line)
에러 다루기
파이썬에서 에러 다루는 방법은 try, except, finally
를 사용하는 것이다.
try:
에러가 발생할 수 있는 코드
except:
에러 발생 시 수행
finally:
예외 발생 여부 상관없이 실행됨
예를 들어보자.
프린터로 출력을 수행하는 코드가 있다.
doc
변수는 text
키를 갖는 딕셔너리 변수이다.
get_printer
컨텍스트 매니저 함수를 통해 doc['txt']
를 출력하고자 한다.
doc
에는 txt
키가 없기 때문에 에러가 발생할 것이다.
error가 발생하고 끝나버리기 때문에 p.disconnect()
가 호출되지 않아 다른 사람이 프린터를 사용할 수 없게된다.
def get_printer(ip):
p = connect_to_printer(ip)
yield
p.disconnect()
print('disconnected from printer')
doc = {'text' : 'This is my text.'}
with get_printer('10.0.34.111') as printer:
printer.print_page(doc['txt'])
에러가 발생하던 말던 프린터 연결 해제는 수행되어야 하기 때문에 finally 부분에 작성하도록한다.
def get_printer(ip):
p = connect_to_printer(ip)
try:
yield
finally:
p.disconnect()
print('disconnected from printer')
doc = {'text' : 'This is my text.'}
with get_printer('10.0.34.111') as printer:
printer.print_page(doc['txt'])
컨텍스트 매니저는 아래와 같은 패턴을 수행하는 경우가 많다.
연결하고 해제하고, 열고 닫고...