Python 표준 모듈--ContextManager 컨 텍스트 관리자 의 구체 적 인 용법
9345 단어 PythonContextManager
이 기능 은 Python 2.5 이후 에 도 입 된 것 으로 코드 를 더욱 읽 을 수 있 고 실수 하기 쉽 지 않다 는 장점 이 있 습 니 다.
1 모듈 소개
몇 년 전 파 이 썬 2.5 는 매우 특별한 키 워드 를 넣 었 는데 그것 이 바로 with 였 다.with 문 구 는 개발 자가 컨 텍스트 관리 자 를 만 들 수 있 도록 합 니 다.문맥 관리자 란 무엇 입 니까?컨 텍스트 관리 자 는 자동 으로 뭔 가 를 시작 하고 끝 낼 수 있 도록 하 는 것 입 니 다.예 를 들 어 파일 을 열 고 내용 을 쓰 고 마지막 으로 파일 을 닫 으 려 고 할 수도 있 습 니 다.이것 은 아마도 상하 문 관리자 의 가장 전형 적 인 예 일 것 이다.사실 with 문 구 를 이용 하여 파일 을 열 었 을 때 Python 은 자동 으로 컨 텍스트 관리 자 를 만 들 었 습 니 다.
with open("test/test.txt","w") as f_obj:
f_obj.write("hello")
만약 당신 이 Python 2.4 를 사용한다 면,당신 은 오래된 방식 으로 이 임 무 를 완성 해 야 합 니 다.
f_obj = open("test/test.txt","w")
f_obj.write("hello")
f_obj.close()
컨 텍스트 관리자 뒤에서 작업 하 는 메커니즘 은 Python 을 사용 하 는 방법 입 니 다:enter__와exit__。컨 텍스트 관리자 가 어떻게 작 동 하 는 지 알 아 보기 위해 컨 텍스트 관리 자 를 만 들 려 고 합 니 다.2 모듈 사용
2.1 컨 텍스트 관리자 클래스 만 들 기
Python 을 계속 사용 하여 파일 을 여 는 것 보다 컨 텍스트 관리 자 를 만 듭 니 다.이 컨 텍스트 관리 자 는 SQLite 데이터베이스 연결 을 만 들 것 입 니 다.작업 이 끝나 면 닫 을 것 입 니 다.다음은 간단 한 예 다.
import sqlite3
class DataConn:
def __init__(self,db_name):
self.db_name = db_name
def __enter__(self):
self.conn = sqlite3.connect(self.db_name)
return self.conn
def __exit__(self,exc_type,exc_val,exc_tb):
self.conn.close()
if exc_val:
raise
if __name__ == "__main__":
db = "test/test.db"
with DataConn(db) as conn:
cursor = conn.cursor()
위 코드 에서 우 리 는 SQLite 데이터베이스 파일 을 가 져 오 는 경 로 를 만 들 었 습 니 다.enter__방법 은 자동 으로 실행 되 고 데이터베이스 연결 대상 을 되 돌려 줍 니 다.현재 우 리 는 데이터베이스 연결 대상 을 가 져 온 후에 커서 를 만들어 데이터베이스 에 데 이 터 를 기록 하거나 데이터 베 이 스 를 조회 합 니 다.우리 가 with 문 구 를 종료 할 때,그것 은 를 호출 합 니 다.exit__방법 은 이 연결 을 실행 하고 닫 는 데 사 용 됩 니 다.컨 텍스트 관리 자 를 만 들 기 위해 다른 방법 을 사용 합 니 다.
2.2 contextlib 를 이용 하여 컨 텍스트 관리 자 를 만 듭 니 다.
Python 2.5 는 with 문 구 를 추가 할 뿐만 아니 라 contextlib 모듈 도 추가 합 니 다.컨 텍스트 lib 의 contextmanager 함 수 를 장식 기로 사용 하여 컨 텍스트 관리 자 를 만 들 수 있 습 니 다.파일 을 열 고 닫 는 데 사용 할 컨 텍스트 관리 자 를 만 들 려 고 시도 합 니 다.
from contextlib import contextmanager
@contextmanager
def file_open(path):
try:
f_obj = open(path,"w")
yield f_obj
except OSError:
print("We had an error!")
finally:
print("Closing file")
f_obj.close()
if __name__ == "__main__":
with file_open("test/test.txt") as fobj:
fobj.write("Testing context managers")
여기 서 contextlib 모듈 에서 contextmanager 를 도입 한 다음 에 우리 가 정의 하 는 file 을 장식 합 니 다.오픈 함수.이것 은 우리 가 Python 의 with 문 구 를 사용 하여 file 를 호출 할 수 있 도록 합 니 다.오픈 함수.함수 에서 우 리 는 파일 을 열 고 yield 를 통 해 전달 합 니 다.최종 메 인 함수 에서 사용 할 수 있 습 니 다.with 구문 이 끝나 면 제어 가 file 로 돌아 갑 니 다.open 함수,yield 구문 뒤의 코드 를 계속 실행 합 니 다.이것 은 최종 적 으로 finally 문 구 를 실행 합 니 다.파일 을 닫 습 니 다.파일 을 열 때 OSError 오류 가 발생 하면 캡 처 되 고 최종 finally 문 구 는 파일 핸들 을 닫 습 니 다.
contextlib.closing(thing)
contextlib 모듈 은 매우 편리 한 도 구 를 제공 합 니 다.첫 번 째 도 구 는 closing 클래스 입 니 다.코드 블록 이 실행 되면 이 벤트 를 닫 습 니 다.Python 공식 문 서 는 다음 과 같은 예 시 를 보 여 주 었 습 니 다.
>>> from contextlib import contextmanager
>>> @contextmanager
... def closing(db):
... try:
... yield db.conn()
... finally:
... db.close()
이 코드 에서,우 리 는 contextmanager 에 포 함 된 닫 기 함 수 를 만 들 었 습 니 다.이것 은 closing 류 와 같다.차이 점 은 우리 가 with 구문 에서 장식 기 가 아 닌 closing 류 자 체 를 사용 할 수 있다 는 것 이다.다음 과 같은 예 를 보 여 주세요.
>>> from contextlib import closing
>>> from urllib.request import urlopen
>>> with closing(urlopen("http://www.google.com")) as webpage:
... for line in webpage:
... pass
이 예제 에서,우 리 는 closing 클래스 에서 url 웹 페이지 를 엽 니 다.우리 가 with 문 구 를 실행 하면 웹 페이지 를 가리 키 는 핸들 이 닫 힙 니 다.contextlib.suppress(*exceptions)
또 다른 도 구 는 Python 3.4 에 추 가 된 suppress 류 입 니 다.이 상하 문 관리 도구 뒤의 이념 은 임의의 수의 이상 을 금지 할 수 있다 는 것 이다.만약 우리 가 FileNotFoundError 이상 을 무시 하고 싶다 면.만약 당신 이 아래 의 상하 문 관리 자 를 썼 다 면,그것 은 정상적으로 작 동 하지 않 을 것 이다.
>>> with open("1.txt") as fobj:
... for line in fobj:
... print(line)
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
FileNotFoundError: [Errno 2] No such file or directory: '1.txt'
보시 다시 피 이 컨 텍스트 관리 자 는 이 이상 을 처리 하지 않 았 습 니 다.이 오 류 를 무시 하고 싶다 면 다음 과 같은 방식 으로 할 수 있 습 니 다.
>>> from contextlib import suppress
>>> with suppress(FileNotFoundError):
... with open("1.txt") as fobj:
... for line in fobj:
... print(line)
이 코드 에서 우 리 는 suppress 를 도입 한 다음 에 우리 가 무시 해 야 할 이상 을 전달 합 니 다.이 예 에서 FileNotFoundation Error 입 니 다.이 코드 를 실행 하려 면 파일 이 존재 하지 않 을 때 아무 일 도 일어나 지 않 았 고 오류 도 발생 하지 않 았 음 을 알 게 될 것 입 니 다.이 컨 텍스트 관리 자 는 다시 사용 할 수 있 으 며,2.4 장 은 구체 적 으로 설명 할 것 입 니 다.contextlib.redirect_stdout/redirect_stderr
contextlib 모듈 은 표준 출력 과 표준 오류 출력 을 재 설정 하 는 도구 도 있 는데 각각 Python 3.4 와 3.5 에 추 가 됩 니 다.이 도구 들 이 가입 되 기 전에 표준 출력 에 대한 방향 을 바 꾸 려 면 다음 과 같은 방식 으로 조작 해 야 합 니 다.
import sys
path = "test/test.txt"
with open(path,"w") as fobj:
sys.stdout = fobj
help(sum)
contextlib 모듈 을 이용 하여 다음 과 같은 방식 으로 조작 할 수 있 습 니 다.
from contextlib import redirect_stdout
path = "test/test.txt"
with open(path,"w") as fobj:
with redirect_stdout(fobj):
help(redirect_stdout)
위의 두 가지 예 에서 우 리 는 모두 표준 출력 을 파일 로 재 설정 합 니 다.Python 의 help 함 수 를 호출 할 때 표준 출력 에 정 보 를 출력 하 는 것 이 아니 라 정 보 를 재 설정 한 파일 에 저장 합 니 다.표준 출력 을 캐 시 나 Tkinter 나 wxPython 같은 인터페이스 에서 가 져 온 파일 제어 형식 으로 바 꿀 수도 있 습 니 다.2.3 ExitStack
ExitStack 은 컨 텍스트 관리자 로 다른 컨 텍스트 관리 와 쉽게 결합 하거나 지 울 수 있 습 니 다.이것 은 어떻게 들 으 면 사람 을 헷 갈 리 게 합 니까?우 리 는 Python 공식 문서 의 예 를 보 겠 습 니 다.아마도 우 리 는 그것 을 더욱 쉽게 이해 할 수 있 을 것 입 니 다.
>>> from contextlib import ExitStack
>>> filenames = ["1.txt","2.txt"]
>>> with ExitStack as stack:
... file_objects = [stack.enter_context(open(filename)) for filename in filenames]
이 코드 는 목록 에 일련의 컨 텍스트 관리 자 를 만 드 는 것 입 니 다.ExitStack 은 레지스터 의 스 택 을 유지 합 니 다.우리 가 with 문 구 를 종료 하면 파일 이 닫 히 고 스 택 은 사진 을 거꾸로 찍 는 순서 로 컨 텍스트 관리 자 를 호출 합 니 다.Python 공식 문서 에서 contextlib 에 관 한 예 가 많 습 니 다.다음 과 같은 기술 을 배 울 수 있 습 니 다.
대부분의 컨 텍스트 관리 자 는 with 구문 에서 만 사용 할 수 있 습 니 다.예제 는 다음 과 같 습 니 다.
>>> from contextlib import contextmanager
>>> @contextmanager
... def single():
... print("Yielding")
... yield
... print("Exiting context manager")
...
>>> context = single()
>>> with context:
... pass
...
Yielding
Exiting context manager
>>> with context:
... pass
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.4/contextlib.py", line 61, in __enter__
raise RuntimeError("generator didn't yield") from None
RuntimeError: generator didn't yield
이 코드 에서 우 리 는 컨 텍스트 관리자 인 스 턴 스 를 만 들 고 Python 의 with 구문 에서 두 번 실행 하려 고 시도 합 니 다.두 번 째 로 실 행 될 때,그것 은 Runtime Error 를 던 졌 다.그런데 만약 에 저희 가 상하 문 관리 자 를 두 번 실행 하고 싶다 면 요?재 활용 가능 한 컨 텍스트 관리 자 를 사용 해 야 합 니 다.전에 사 용 했 던 redirect 를 사용 합 시다.stdout 이 컨 텍스트 관리 자 를 예제 로 합 니 다.
>>> from contextlib import redirect_stdout
>>> from io import StringIO
>>> stream = StringIO()
>>> write_to_stream = redirect_stdout(stream)
>>> with write_to_stream:
... print("Write something to the stream")
... with write_to_stream:
... print("Write something else to stream")
...
>>> print(stream.getvalue())
Write something to the stream
Write something else to stream
이 코드 에서 우 리 는 컨 텍스트 관리 자 를 만 들 었 습 니 다.모두 StringIO(메모리 의 파일 흐름)에 데 이 터 를 기록 합 니 다.이 코드 는 이전 처럼 Runtime Error 오 류 를 던 지지 않 고 정상적으로 작 동 합 니 다.그 이 유 는 redirect 입 니 다.stdout 은 다시 사용 할 수 있 습 니 다.두 번 호출 할 수 있 습 니 다.물론 실제 예 는 더 많은 함수 호출 이 있 고 더욱 복잡 할 것 이다.다시 사용 할 수 있 는 컨 텍스트 관리자 가 반드시 스 레 드 가 안전 한 것 은 아니 므 로 주의해 야 합 니 다.스 레 드 에서 사용 할 필요 가 있다 면 Python 문 서 를 자세히 읽 으 십시오.2.5 총화
문맥 관리 자 는 재 미 있 고 편리 합 니 다.나 는 대 화 를 열 고 닫 는 등 자동 테스트 에서 자주 사용한다.이제 Python 에 내 장 된 도 구 를 사용 하여 컨 텍스트 관리 자 를 만 들 수 있 을 것 입 니 다.contextlib 에 관 한 파 이 썬 의 문 서 를 계속 읽 을 수 있 습 니 다.그곳 에는 본문 이 덮어 쓰 지 않 은 지식 이 많 습 니 다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Python의 None과 NULL의 차이점 상세 정보그래서 대상 = 속성 + 방법 (사실 방법도 하나의 속성, 데이터 속성과 구별되는 호출 가능한 속성 같은 속성과 방법을 가진 대상을 클래스, 즉 Classl로 분류할 수 있다.클래스는 하나의 청사진과 같아서 하나의 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.