Context manager và câu lệnh with trong Python

Bạn đã dùng with open(...) để đọc file. Cơ chế đứng sau nó gọi là context manager — và bạn hoàn toàn có thể tự viết một cái.

Vì sao cần with?

# Cách dễ quên đóng file
f = open("data.txt")
noi_dung = f.read()
f.close()   # nếu ở giữa có lỗi, dòng này không bao giờ chạy

# Cách an toàn
with open("data.txt") as f:
    noi_dung = f.read()
# file tự đóng, kể cả khi có ngoại lệ

Tự viết bằng class

class MoKetNoi:
    def __enter__(self):
        print("Mở kết nối")
        self.conn = "connection"
        return self.conn

    def __exit__(self, exc_type, exc_value, tb):
        print("Đóng kết nối")
        return False   # False = không nuốt ngoại lệ

with MoKetNoi() as conn:
    print("Đang dùng", conn)

Cách gọn hơn với contextlib

from contextlib import contextmanager
import time

@contextmanager
def do_thoi_gian(ten):
    bat_dau = time.perf_counter()
    try:
        yield
    finally:
        print(f"{ten}: {time.perf_counter() - bat_dau:.3f}s")

with do_thoi_gian("Tải dữ liệu"):
    time.sleep(1)

Phần trước yield chạy khi vào khối with, phần trong finally chạy khi ra — kể cả khi có lỗi.

Mở nhiều tài nguyên cùng lúc

with open("vao.txt") as f_vao, open("ra.txt", "w") as f_ra:
    for dong in f_vao:
        f_ra.write(dong.upper())

Dùng ở đâu trong thực tế

  • Kết nối database — tự commit hoặc rollback
  • Khóa (lock) trong đa luồng — tự nhả khóa
  • Đổi thư mục làm việc tạm thời rồi trả về chỗ cũ
  • Đo thời gian, ghi log bao quanh một đoạn xử lý

Quy tắc đơn giản: hễ có cặp “mở — đóng”, “bật — tắt”, “chiếm — nhả”, hãy nghĩ tới context manager.

Lên đầu trang