Python의 컨텍스트 관리자.
21336 단어 pythonprogrammingbeginners
컨텍스트 관리자란 무엇입니까?
다음은 Python의 공식 문서에 나와 있는 내용입니다.
A context manager is an object that defines the runtime context to be established when executing a with statement. The context manager handles the entry into, and the exit from, the desired runtime context for the execution of the block of code. Context managers are normally invoked using the with statement, but can also be used by directly invoking their methods. – Python Docs
그러나 그것은 모든 기반을 덮고 있을 뿐입니다. 단순화 된 버전을 이해합시다.
프로그래머는 때때로 파일, 데이터베이스 연결, 잠금 등과 같은 외부 리소스를 사용합니다. 컨텍스트 관리자를 사용하면 다음을 지정하여 이러한 리소스를 관리할 수 있습니다.
컨텍스트 관리자가 필요한 이유는 무엇입니까?
다음 예를 고려하십시오.
for _ in range(100000):
file = open("foo.txt", "w")
files.append(f)
file.close()
파일 설명자가 매번 해제되도록 하기 위해 close()
메서드를 호출하고 있음을 주목하세요. 그렇게 하지 않으면 OS는 결국 파일 설명자를 열 수 있는 허용 한도를 다 써버릴 것입니다.
그러나 컨텍스트 관리자를 사용하여 위 코드의 보다 파이썬적인 버전을 작성합니다.
for _ in range(100000):
with open("foo.txt", "r") as f:
files.append(f)
여기 open("foo.txt", "r")
는 with
문을 사용하여 활성화되는 컨텍스트 관리자입니다. 명시적으로 파일을 닫을 필요가 없었고 컨텍스트 관리자가 처리해 주었습니다. 마찬가지로 Python에는 작업을 더 쉽게 해주는 미리 정의된 다른 컨텍스트 관리자가 있습니다.
자체 컨텍스트 관리자를 정의할 수 있습니까?
예. 사용자 정의 컨텍스트 관리자를 정의하는 두 가지 방법이 있습니다.
for _ in range(100000):
file = open("foo.txt", "w")
files.append(f)
file.close()
for _ in range(100000):
with open("foo.txt", "r") as f:
files.append(f)
예. 사용자 정의 컨텍스트 관리자를 정의하는 두 가지 방법이 있습니다.
클래스 기반 컨텍스트 관리자
파일 예제를 계속 진행하고 open()
에뮬레이트할 컨텍스트 관리자를 정의해 보겠습니다.
files = []
class Open():
def __init__(self, filename, mode):
self.filename = filename
self.mode = mode
def __enter__(self):
self.open_file = open(self.filename, self.mode)
print("Enter called")
return self.open_file
def __exit__(self, *args):
print("Exit Called")
self.open_file.close()
for _ in range(100000):
with Open('foo.txt', 'w') as f:
files.append(f)
files = []
class Open():
def __init__(self, filename, mode):
self.filename = filename
self.mode = mode
def __enter__(self):
self.open_file = open(self.filename, self.mode)
print("Enter called")
return self.open_file
def __exit__(self, *args):
print("Exit Called")
self.open_file.close()
for _ in range(100000):
with Open('foo.txt', 'w') as f:
files.append(f)
__enter__
메서드는 리소스를 획득할 때 수행할 작업, 즉 파일 개체를 제공하는 방법을 알려줍니다. __exit__
메서드는 컨텍스트 관리자를 종료할 때(즉, 파일을 닫을 때) 수행할 작업을 정의합니다. __enter__
와 __exit__
가 어떻게 호출되는지 볼 수 있습니다. 오류 처리
파이썬
FileNotFoundError
으로 open()
를 어떻게 처리합니까?try:
with open("foo.txt", "r") as f:
content = f.readlines()
except FileNotFoundError as e:
print("Hey, file isn't there. Let's log it.")
파일을 열 때마다 필요한 기본 오류 처리 코드입니다. 사용자 정의 컨텍스트 관리자로 DRY를 시도해 보겠습니다.
class Open():
def __init__(self, filename, mode):
self.filename = filename
self.mode = mode
def __enter__(self):
print("Enter called")
try:
self.open_file = open(self.filename, self.mode)
return self.open_file
except FileNotFoundError as e:
print("Hey, file isn't there. Let's log it.")
def __exit__(self, exc_type, exc_value, exc_traceback): #notice the parameters
print("Exit Called")
if(exc_type is None):
self.open_file.close()
return True
else:
return True
with Open("foo.txt", "r") as f:
content = f.readlines()
__exit__
의 변경 사항exc_type
는 __enter__
에서 오류를 처리하는 동안 얻을 수 있는 오류 클래스 유형입니다(이 경우 AttributeError). exc_value
는 __enter__
에서 오류를 처리하는 동안 얻게 될 오류 값입니다. exc_traceback
는 __enter__
에서 오류를 처리하는 동안 얻게 될 오류의 역추적입니다. True
를 반환합니다(exc_traceback
매개변수와 혼동하지 마십시오). 또 다른 실제 사례
class DatabaseHandler():
def __init__(self):
self.host = '127.0.0.1'
self.user = 'dev'
self.password = 'dev@123'
self.db = 'foobar'
self.port = '5432'
self.connection = None
self.cursor = None
def __enter__(self):
self.connection = psycopg2.connect(
user=self.user,
password=self.password,
host=self.host,
port=self.port,
database=self.db
)
self.cursor = self.connection.cursor()
return self.cursor
def __exit__(self, *args):
self.cursor.close()
self.connection.close()
기능 기반 컨텍스트 관리자
함수 기반 컨텍스트 관리는 contextlib
라는 라이브러리를 사용하여 수행되며 이를 통해 간단한 생성기 함수를 컨텍스트 관리자로 변경할 수 있습니다. 일반적인 청사진은 다음과 같습니다.
from contextlib import contextmanager
@contextmanager
def foobar():
print("What you would typically put in __enter__")
yield {}
print("What you would typically put in __exit__")
with foobar() as f:
print(f)
from contextlib import contextmanager
@contextmanager
def foobar():
print("What you would typically put in __enter__")
yield {}
print("What you would typically put in __exit__")
with foobar() as f:
print(f)
contextmanager
데코레이터는 모든 생성기 기능을 컨텍스트 관리자로 전환하는 데 사용됩니다. yield
는 컨텍스트 관리자의 __enter__
부분과 __exit__
부분 사이에서 구분자로 작동합니다.파일 처리
from contextlib import contextmanager
@contextmanager
def open_(filename, mode):
print("SETUP")
open_file = open(filename, mode)
try:
print("EXECUTION")
yield open_file
except:
print("Hey, file isn't there. Let's log it.")
finally:
print("CLEAN-UP")
open_file.close()
with open_("somethign.txt", "w") as f: #notice the mode
content = f.readlines() #you cannot read on write mode
사용자가 파일 객체로 무엇을 할 지 모르기 때문에
yield
를 try
블록으로 래핑합니다. 의도하지 않은 방식으로 사용하려고 할 수 있습니다(위 참조).데이터베이스 연결
from contextlib import contextmanager
@contextmanager
def database_handler():
try:
host = '127.0.0.1'
user = 'dev'
password = 'dev@123'
db = 'foobar'
port = '5432'
connection = psycopg2.connect(
user=user,
password=password,
host=host,
port=port,
database=db
)
cursor = connection.cursor()
yield cursor
except:
print("Hey, file isn't there. Let's log it.")
finally:
cursor.close()
connection.close()
자원
우리는 컨텍스트 관리자에 대한 소개만 다루었지만 이는 빙산의 일각에 불과하며 흥미로운 사용 사례가 많이 있습니다. 내가 찾은 몇 가지 흥미로운 링크는 다음과 같습니다.
Reference
이 문제에 관하여(Python의 컨텍스트 관리자.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/sigmapie8/context-managers-in-python-5fgc텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)