Context managers trong Python cung cấp một cách mạnh mẽ để quản lý tài nguyên một cách hiệu quả và an toàn. Một context manager trong Python là một đối tượng định nghĩa một ngữ cảnh chạy để sử dụng với câu lệnh with . Nó đảm bảo rằng các thao tác thiết lập và dọn dẹp được thực hiện tự động.
Ví dụ, khi làm việc với các thao tác tệp, các trình quản lý ngữ cảnh xử lý việc mở và đóng tệp, đảm bảo rằng tài nguyên được quản lý đúng cách.
Các trình quản lý ngữ cảnh trong Python hoạt động bằng cách triển khai các phương thức __enter__() và __exit__() (hoặc các phương thức tương đương bất đồng bộ cho các thao tác async). Các phương thức này đảm bảo rằng tài nguyên được lấy và giải phóng một cách chính xác. Ngoài ra, mô-đun contextlib của Python còn đơn giản hóa việc tạo ra các trình quản lý ngữ cảnh tùy chỉnh.
Dưới đây là một ví dụ đơn giản minh họa cách một trình quản lý ngữ cảnh hoạt động với các thao tác tệp trong Python.
with open('example.txt', 'w') as file: file.write('Hello, Tutorialspoint!')
Trong ví dụ này, một tệp được mở ở chế độ ghi, và sau đó tự động đóng khi khối bên trong câu lệnh with được thoát.
Python hỗ trợ cả trình quản lý ngữ cảnh đồng bộ và bất đồng bộ. Mỗi loại có các phương thức cụ thể cần được triển khai để quản lý vòng đời của ngữ cảnh.
Các trình quản lý ngữ cảnh đồng bộ được thực hiện bằng cách sử dụng các phương thức __enter__() và __exit__() .
Phương thức __enter__(self) được gọi khi thực thi vào ngữ cảnh của câu lệnh with. Phương thức này nên trả về tài nguyên sẽ được sử dụng trong khối with.
Example
Dưới đây là một ví dụ đơn giản về việc tạo quản lý ngữ cảnh của riêng chúng ta bằng cách sử dụng các phương thức __enter__() và __exit__() .
class MyContextManager: def __enter__(self): print("Entering the context") return self def __exit__(self, exc_type, exc_value, traceback): print("Exiting the context") with MyContextManager(): print("body")
Khi thực thi đoạn mã trên, bạn sẽ nhận được output −
Entering the context body Exiting the context
Phương thức __exit__(self, exc_type, exc_value, traceback) được gọi khi thực thi rời khỏi ngữ cảnh của câu lệnh with. Nó có thể xử lý các ngoại lệ nếu có xảy ra, và nó trả về một cờ Boolean cho biết liệu ngoại lệ có nên bị подавлено hay không.
Ví dụ này minh họa cách tạo trình quản lý ngữ cảnh của riêng chúng ta và cách các phương thức __exit__() xử lý các ngoại lệ.
class MyContextManager: def __enter__(self): print("Entering the context") return self def __exit__(self, exc_type, exc_value, traceback): print("Exiting the context") if exc_type: print("An exception occurred") return True # Suppress exception with MyContextManager(): print("body") name = "Python"/3 #to raise an exception
Trong khi thực thi đoạn mã trên, bạn sẽ nhận được output −
Entering the context body Exiting the context An exception occurred
Tương tự như các trình quản lý ngữ cảnh đồng bộ, các trình quản lý ngữ cảnh bất đồng bộ cũng được triển khai bằng cách sử dụng hai phương thức là __aenter__() và __aexit__() . Những phương thức này được sử dụng trong các câu lệnh async with .
The __aenter__(self) Method − Nó phải trả về một đối tượng có thể chờ (awaitable) mà sẽ được chờ khi vào ngữ cảnh.
__aexit__(self, exc_type, exc_value, traceback) Method − Nó phải trả về một đối tượng có thể chờ (awaitable) mà sẽ được chờ khi thoát khỏi ngữ cảnh.
Example
Dưới đây là ví dụ về việc tạo một lớp trình quản lý ngữ cảnh bất đồng bộ −
import asyncio class AsyncContextManager: async def __aenter__(self): print("Entering the async context class") return self async def __aexit__(self, exc_type, exc_value, traceback): print("Exiting the async context class") if exc_type: print("Exception occurred") return True async def main(): async with AsyncContextManager(): print("Inside the async context") name = "Python"/3 #to raise an exception asyncio.run(main())
Khi thực thi đoạn mã trên, bạn sẽ nhận được đầu ra sau:
Entering the async context class Inside the async context Exiting the async context class Exception occurred
Mô-đun contextlib trong thư viện chuẩn của Python cung cấp các tiện ích để tạo các trình quản lý ngữ cảnh dễ dàng hơn.
Hàm contextlib.contextmanager() là một decorator cho phép bạn tạo ra các hàm factory cho các trình quản lý ngữ cảnh với câu lệnh with. Nó loại bỏ nhu cầu định nghĩa một lớp riêng biệt hoặc triển khai các phương thức __enter__() và __exit__() một cách riêng lẻ.
Example
Dưới đây là một ví dụ sử dụng contextlib.contextmanager để tạo một hàm quản lý ngữ cảnh.
from contextlib import contextmanager @contextmanager def my_context_manager(): print("Entering the context manager method") try: yield finally: print("Exiting the context manager method") with my_context_manager(): print("Inside the context")
Khi thực thi đoạn mã trên, bạn sẽ nhận được đầu ra sau:
Entering the context manager method Inside the context Exiting the context manager method
Mô-đun contextlib cũng cung cấp asynccontextmanager, được thiết kế đặc biệt để tạo ra các quản lý ngữ cảnh bất đồng bộ. Nó tương tự như contextmanager và loại bỏ nhu cầu phải định nghĩa một lớp riêng biệt hoặc thực hiện các phương thức __aenter__() và __aexit__() một cách riêng lẻ.
Example
Dưới đây là một ví dụ minh họa việc sử dụng contextlib.asynccontextmanager() để tạo một hàm quản lý ngữ cảnh bất đồng bộ.
import asyncio from contextlib import asynccontextmanager @asynccontextmanager async def async_context_manager(): try: print("Entering the async context") # Perform async setup tasks if needed yield finally: # Perform async cleanup tasks if needed print("Exiting the async context") async def main(): async with async_context_manager(): print("Inside the async context") await asyncio.sleep(1) # Simulating an async operation # Run the asyncio event loop asyncio.run(main())
Khi thực thi đoạn mã trên, bạn sẽ nhận được đầu ra sau:
Entering the async context Inside the async context Exiting the async context