Menu
CoddyTech

Trình quản lý ngữ cảnh

Thuộc phần Lập trình hướng đối tượng trong hành trình Python của Coddy. Bài học 41 trên 64.

Trình quản lý ngữ cảnh giúp bạn cấp phát và giải phóng tài nguyên đúng lúc cần thiết. Chúng đảm bảo việc dọn dẹp diễn ra đúng cách ngay cả khi có lỗi.

Đây là ví dụ phổ biến nhất khi dùng câu lệnh with:

with open('example.txt', 'w') as file:
    file.write('Hello, world!')
# Tệp tự động đóng tại đây

Tệp sẽ tự động đóng sau khối lệnh, ngay cả khi xảy ra ngoại lệ.

Tạo context manager của riêng bạn bằng cách triển khai các phương thức __enter__ và __exit__:

class MyContext:
    def __enter__(self):
        print("Entering the context")
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("Exiting the context")
        return False  # Đừng chặn các ngoại lệ

Hãy dùng context manager tùy chỉnh của bạn:

with MyContext() as ctx:
    print("Inside the context")

Đầu ra:

Entering the context
Inside the context
Exiting the context

Tạo một trình quản lý ngữ cảnh thiết thực hơn cho các kết nối cơ sở dữ liệu:

class DatabaseConnection:
    def __init__(self, db_name):
        self.db_name = db_name
        self.connection = None
    
    def __enter__(self):
        print(f"Connecting to {self.db_name}")
        self.connection = f"Connection to {self.db_name}"
        return self.connection
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        print(f"Closing connection to {self.db_name}")
        self.connection = None

with DatabaseConnection("users_db") as conn:
    print(f"Using {conn}")
    print("Performing database operations...")

Xử lý ngoại lệ trong trình quản lý ngữ cảnh:

class SafeContext:
    def __enter__(self):
        print("Setting up resources")
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("Cleaning up resources")
        if exc_type:
            print(f"An exception occurred: {exc_val}")
        return False  # Không chặn ngoại lệ

with SafeContext():
    print("Working with resources")
    # raise ValueError("Something went wrong")  # Bỏ dấu chú thích để kiểm tra

Đầu ra:

Connecting to users_db
Using Connection to users_db
Performing database operations...
Closing connection to users_db
Setting up resources
Working with resources
Cleaning up resources

Phương thức __exit__ nhận ba tham số:

  • exc_type: Kiểu ngoại lệ (hoặc None)
  • exc_val: Giá trị ngoại lệ (hoặc None)
  • exc_tb: Thông tin truy vết ngoại lệ (hoặc None)

Điểm chính: Trình quản lý ngữ cảnh dùng phương thức __enter__ và __exit__ để quản lý tài nguyên. Câu lệnh with tự động gọi các phương thức này, đảm bảo thiết lập và dọn dẹp đúng cách. Cách này đặc biệt hữu ích với tệp, kết nối cơ sở dữ liệu và các tài nguyên khác cần được dọn dẹp đầy đủ.

challenge icon

Thử thách

Dễ

Trong thử thách này, bạn sẽ triển khai một lớp quản lý ngữ cảnh để đo thời gian đã trôi qua từ lúc vào đến lúc thoát khỏi một khối ngữ cảnh.

  • timer.py - Chứa phần triển khai lớp Timer (bạn sẽ chỉnh sửa tệp này)
  • driver.py - Chứa các test case toàn diện (không chỉnh sửa)

Triển khai trình quản lý ngữ cảnh Timer trong timer.py theo các chú thích TODO. Lớp này cần:

  1. Ghi lại thời điểm bắt đầu khi vào ngữ cảnh
  2. Ghi lại thời điểm kết thúc khi thoát khỏi ngữ cảnh
  3. Tính toán và hiển thị thời gian đã trôi qua

Tự làm thử

from timer import Timer
import time

# Xử lý test case
test_case = input()

if test_case == "basic_test":
    # Kiểm tra chức năng cơ bản
    with Timer():
        # Mô phỏng một tác vụ
        time.sleep(2)  # Lệnh này khiến chương trình chờ 2 giây

elif test_case == "nested_contexts":
    # Kiểm tra các trình quản lý ngữ cảnh lồng nhau
    with Timer():
        time.sleep(1)
        with Timer():
            time.sleep(1)

elif test_case == "exception_handling":
    # Kiểm tra cách xử lý ngoại lệ trong ngữ cảnh
    try:
        with Timer():
            time.sleep(1)
            raise ValueError("Test exception")
    except ValueError as e:
        print(f"Caught exception: {e}")

elif test_case == "zero_sleep":
    # Kiểm tra với thời gian chờ tối thiểu
    with Timer():
        time.sleep(0.001)

elif test_case == "multiple_timers":
    # Kiểm tra nhiều bộ đếm thời gian liên tiếp
    with Timer():
        time.sleep(1)
    
    with Timer():
        time.sleep(0.5)
    
    with Timer():
        time.sleep(2)

elif test_case == "as_decorator":
    # Kiểm tra bộ đếm thời gian trong một hàm
    def timed_function():
        with Timer():
            time.sleep(2)
    
    timed_function()

else:
    # Kiểm tra mặc định: chức năng cơ bản
    with Timer():
        # Mô phỏng một tác vụ
        time.sleep(2)  # Lệnh này khiến chương trình chờ 2 giây
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Lập trình hướng đối tượng

Tự luyện tập: Trình biên dịch Python online