Cách quản lý tài nguyên trong Python bằng trình quản lý ngữ cảnh

Đảm bảo quản lý tài nguyên hiệu quả bằng trình quản lý ngữ cảnh trong Python thật dễ dàng. Dưới đây là hướng dẫn chi tiết.

Quản lý tài nguyên trong Python

Việc quản lý tài nguyên hợp lí rất quan trọng khi xây dựng ứng dụng để tránh rò rỉ bộ nhớ, đảm bảo dọn dẹp đúng cách và duy trì trạng thái ổn định của ứng dụng. Trình quản lý ngữ cảnh cung cấp giải pháp hiệu quả cho tình huống này. Nó sắp xếp hợp lí quản lý tài nguyên bằng cách tự động hóa quy trình thu thập và giải phóng tài nguyên.

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

Về cơ bản, trình quản lý ngữ cảnh là  một đối tượng xác định các phương thức thu thập và giải phóng tài nguyên khi cần. Trình quản lý ngữ cảnh hữu ích vì chúng có thể sắp xếp quản lý tài nguyên theo cấu trúc rõ ràng, đơn giản và chính xác. Dùng trình quản lý ngữ cảnh có thể giảm trùng lặp code và khiến nó dễ đọc hơn.

Hãy nghĩ tới chương trình phải ghi dữ liệu trong một file. Bất cứ khi nào ứng dụng cần ghi lại thứ gì đó, bạn phải tự tay mở và đóng file log vì không có trình quản lý ngữ cảnh. Tuy nhiên, nếu sử dụng nó, bạn dễ dàng hợp lý hóa thiết lập và giải cấu trúc tài nguyên ghi nhật ký, đảm bảo xử lý đúng cách nhiệm vụ ghi nhật ký.

Lệnh with

Lệnh with trong Python cung cấp một cách dùng trình quản lý ngữ cảnh. Ngay cả khi các ngoại lệ xảy ra trong khi khối code được triển khai, nó đảm bảo rằng các tài nguyên thu được được giải phóng phù hợp sau khi được dùng đúng như dự định.

with context_manager_expression as resource:
    # Khối code sử dụng tài nguyên này
# Tài nguyên tự động được giải phóng khi khối code thoát

Bằng cách dùng lệnh with, bạn cho trình quản lý ngữ cảnh kiểm soát quản lý tài nguyên, và tập trung tốt hơn vào logic của ứng dụng.

Sử dụng trình quản lý ngữ cảnh có sẵn

Python cung cấp các trình quản lý ngữ cảnh có sẵn cho những trường hợp phổ biến. Bạn sẽ thấy hai ví dụ: xử lý file bằng hàm open() và quản lý kết nối mạng bằng mô đun socket.

Xử lý file bằng open()

Hàm open() là trình quản lý ngữ cảnh sẵn có để dùng cho xử lý file. Nó thường xuyên được dùng cho việc đọc hoặc ghi file và trả về một đối tượng file. Khi dùng một trình quản lý ngữ cảnh cho quản lý file, nó tránh sự cố hỏng dữ liệu tiềm ẩn bằng cách tự động đóng file khi không còn cần thiết.

with open('file.txt', 'r') as file:
    content = file.read()
    # Xử lý nội dung
# File tự động đóng sau khi thoát khối code

Kết nối mạng bằng socket()

Mô đun socket cung cấp trình quản lý ngữ cảnh cho các socket mạng. Trình quản lý ngữ cảnh có thể đảm bảo thiết lập phù hợp và phân chia thích hợp khi làm việc với những kết nối mạng, ngăn lỗ hổng kết nối.

import socket

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect(('localhost', 8080))
    # Gửi/nhận dữ liệu trên socket
# Socket tự động được đóng sau khi thoát khối

Triển khai trình quản lý ngữ cảnh tùy biến

Trình quản lý ngữ cảnh tùy biến cho phép bạn gói gọn việc quản lý tài nguyên cụ thể hay hành vi trong code. Python cung cấp các cách khác nhau để tạo trình quản lý ngữ cảnh tùy biến cho từng trường hợp khác nhau. Tại đây, bạn sẽ khám phá phương pháp dựa trên class và hàm.

Trình quản lý ngữ cảnh bằng phương pháp dựa trên class

Trong phương pháp dựa trên class, bạn xác định một class triển khai __enter__ __exit__ magic hoặc dunder. Phương thức __enter__ khởi tạo và trả về tài nguyên bạn muốn quản lý, trong khi phương thức __exit__ đảm bảo việc dọn dẹp thích hợp, ngay cả khi có ngoại lệ.

class CustomContext:
    def __enter__(self):
        # Yêu cầu tài nguyên
        return resource

    def __exit__(self, exc_type, exc_value, traceback):
        # Giải phóng tài nguyên
        pass

Xem xét nhiệm vụ tại nơi mà bạn phải chạy một số quá trình. Nhiệm vụ này cần một trình quản lý ngữ cảnh sẽ đơn giản hóa quá trình thực thi đồng thời tất cả các quy trình, cung cấp quản lý tài nguyên, đồng bộ hóa và quản lý lỗi chính xác.

import multiprocessing
import queue

class ProcessPool:
    def __init__(self, num_processes):
        self.num_processes = num_processes
        self.processes = []

    def __enter__(self):
        self.queue = multiprocessing.Queue()

        for _ in range(self.num_processes):
            process = multiprocessing.Process(target=self._worker)
            self.processes.append(process)
            process.start()

        return self

    def __exit__(self, exc_type, exc_value, traceback):
        for process in self.processes:
            # Gửi giá trị dự phòng để báo hiệu quá trình worker nghỉ
            self.queue.put(None)
        for process in self.processes:
            process.join()

    def _worker(self):
        while True:
            number = self.queue.get()
            if number is None:
                break
            calculate_square(number)

def calculate_square(number):
    result = number * number
    print(f"The square of {number} is {result}")

if __name__ == "__main__":
    numbers = [1, 2, 3, 4, 5]

    # Sử dụng
    with ProcessPool(3) as pool:
        for num in numbers:
            pool.queue.put(num)

    # Tự động bắt đầu các quá trình và  
    # được nối khi thoát khối "with"

Trình quản lý ngữ cảnh ProcessPool quản lý một nhóm công nhân, phân bổ nhiệm vụ cho những quá trình này để thực thi đồng thời. Sự song song này có thể cho bạn sử dụng hiệu quả hơn các lõi CPU sẵn có và chạy nhiệm vụ nhanh hơn triển khai tuần tự chúng trong một quá trình đơn lẻ.

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

Trình quản lý ngữ cảnh bằng phương pháp dựa trên hàm

Mô đun contextlib cung cấp decorator @contextmanager để tạo trình quản lý ngữ cảnh bằng các hàm khởi tạo. Các decorator cho phép bạn thêm chức năng cho một hàm mà không cần phải chỉnh sửa nó.

Trong hàm tạo được “decorate”, bạn có thể dùng lệnh yield final để chỉ vị trí tài nguyên cần thiết và nơi nó được phát hành.

from contextlib import contextmanager

@contextmanager
def custom_context():
    # Code để yêu cầu tài nguyên
    resource = ...

    try:
        yield resource # Resource is provided to the with block
    finally:
        # Code để giải phóng tài nguyên
        pass

Giả sử bạn muốn phát triển một trình quản lý ngữ cảnh mà tính thời gian thực thi một khối code. Bạn có thể làm việc này bằng cách triển khai một chiến lược dựa trên hàm.

import time
from contextlib import contextmanager

@contextmanager
def timing_context():
    start_time = time.time()

    try:
        yield
    finally:
        end_time = time.time()
        elapsed_time = end_time - start_time
        print(f"Elapsed time: {elapsed_time} seconds")

# Cách dùng
with timing_context():
    # Khối code đo thời gian thực thi
    time.sleep(2)

Ở ví dụ này, trình quản lý ngữ cảnh timing_context ghi lại thời gian bắt đầu và kết thúc khối code và tính thời gian đã trôi qua khi khối code thoát ra.

IDLE Shell

Bằng cách sử dụng một trong hai phương pháp tiếp cận trên, bạn có thể xây dựng trình quản lý ngữ cảnh tùy chỉnh để gói gọn logic quản lý tài nguyên phức tạp và những hoạt động lặp đi lặp lại, cải thiện các sắp xếp và bảo trì code.

Trên đây là những thông tin cơ bản bạn cần biết về cách quản lý tài nguyên trong Python bằng trình quản lý ngữ cảnh. Hi vọng bài viết hữu ích với các bạn.

Thứ Năm, 14/09/2023 14:35
51 👨 338
0 Bình luận
Sắp xếp theo
    ❖ Python