2011-11-21 45 views
5

[Tôi xin lỗi vì tiêu đề inept; Tôi không thể nghĩ ra điều gì tốt hơn. Đề xuất cho một tiêu đề tốt hơn được chào đón.]Làm cách nào để cung cấp chức năng giống như tuyên bố cho lớp học?

Tôi muốn triển khai giao diện cho HDF5 tệp hỗ trợ đồng thời đa cấp thông qua khóa tệp. Môi trường dự định cho mô-đun này là một cụm Linux truy cập vào một đĩa được chia sẻ trên NFS. Mục đích là để cho phép truy cập đồng thời (trên NFS) vào cùng một tệp bằng nhiều tiến trình song song chạy trên một vài máy chủ khác nhau.

Tôi muốn có thể triển khai chức năng khóa thông qua lớp trình bao bọc cho lớp h5py.File. (h5py đã cung cấp hỗ trợ cho chủ đề -level đồng thời, nhưng thư viện HDF5 cơ bản không phải là thread-safe.)

Nó sẽ là tuyệt vời nếu tôi có thể làm điều gì đó theo tinh thần điều này:

class LockedH5File(object): 
    def __init__(self, path, ...): 
     ... 
     with h5py.File(path, 'r+') as h5handle: 
      fcntl.flock(fcntl.LOCK_EX) 
      yield h5handle 
     # (method returns) 

Tôi nhận ra rằng mã trên là sai, nhưng tôi hy vọng nó chuyển tải ý tưởng chính: cụ thể là, để có biểu thức LockedH5File('/path/to/file') cung cấp xử lý mở cho mã máy khách, sau đó có thể thực hiện các hoạt động đọc/ghi tùy ý khác nhau trên đó. Khi xử lý này đi ra khỏi phạm vi, destructor của nó đóng cửa xử lý, do đó phát hành khóa.

Các mục tiêu đó thúc đẩy sự sắp xếp này là hai lần:

  1. tách việc tạo ra các xử lý (bằng mã thư viện) từ hoạt động mà sau đó được yêu cầu trên tay cầm (do khách hàng mã) và

  2. đảm bảo rằng tay cầm được đóng và khóa được giải phóng, bất kể điều gì xảy ra trong quá trình thực thi mã intervening (ví dụ: ngoại lệ, unhandled tín hiệu, lỗi nội bộ Python).

Làm cách nào tôi có thể đạt được hiệu ứng này bằng Python?

Cảm ơn!

Trả lời

6

Để thực hiện công việc này, lớp học của bạn cần triển khai context manager protocol. Ngoài ra, hãy viết chức năng máy phát điện bằng cách sử dụng trang trí contextlib.contextmanager.

lớp học của bạn xấp xỉ có thể trông như thế này (các chi tiết của h5py sử dụng có lẽ là sai lầm khủng khiếp):

class LockedH5File(object): 
    def __init__(self, path, ...): 
     self.h5file = h5py.File(path, 'r+') 
    def __enter__(self): 
     fcntl.flock(fcntl.LOCK_EX) 
     return self.h5file 
    def __exit__(self, exc_type, exc_val, exc_tb): 
     self.h5file.close() 
2

Vâng, một người quản lý bối cảnh và with tuyên bố. Nói chung, các trình phá hủy trong Python không được bảo đảm để chạy ở tất cả, vì vậy bạn không nên dựa vào chúng như bất kỳ thứ gì khác ngoài dọn dẹp không an toàn. Cung cấp __enter____exit__ phương pháp, và sử dụng nó như

with LockedFile(...) as fp: 
    # ... 
8

đối tượng có thể được sử dụng trong báo cáo with được gọi là quản lý bối cảnh; và họ thực hiện một giao diện đơn giản.Họ phải cung cấp hai phương thức, phương thức __enter__, không có đối số và có thể trả về bất kỳ thứ gì (sẽ được gán cho biến trong phần as) và phương thức __exit__, có ba đối số (sẽ được điền bằng kết quả của sys.exc_info()) và trả về khác 0 để chỉ ra rằng một ngoại lệ đã được xử lý. Ví dụ của bạn có thể trông giống như:

class LockedH5File(object): 
    def __init__(self, path, ...): 
     self.path = path 

    def __enter__(self): 
     self.h5handle = h5handle = h5py.File(self.path, 'r+') 
     fcntl.flock(fcntl.LOCK_EX) 
     return h5handle 

    def __exit__(self, exc_type, exc_info, exc_tb): 
     self.h5handle.close() 
Các vấn đề liên quan