2010-09-22 24 views
25

Tôi phải mở một đối tượng giống như tệp trong python (đó là kết nối nối tiếp thông qua/dev /) và sau đó đóng nó. Điều này được thực hiện nhiều lần trong một số phương pháp của lớp học của tôi. Làm thế nào tôi đã làm nó đã được mở tập tin trong constructor, và sau đó đóng nó trong destructor. Tôi nhận được lỗi lạ mặc dù và tôi nghĩ rằng nó đã làm với thu gom rác và như vậy, tôi vẫn không được sử dụng để không biết chính xác khi đối tượng của tôi đang bị xóa = \Thực hiện việc sử dụng 'with object() như f' trong lớp tùy chỉnh trong python

Lý do tôi đã làm điều này là bởi vì tôi phải sử dụng tcsetattr với một loạt các thông số mỗi khi tôi mở nó và nó gây phiền nhiễu khi làm tất cả những điều đó khắp nơi. Vì vậy, tôi muốn thực hiện một lớp bên trong để xử lý tất cả những gì để tôi có thể sử dụng nó làm
with Meter('/dev/ttyS2') as m:

tôi đang tìm kiếm trực tuyến và tôi không thể tìm thấy một câu trả lời thực sự tốt về cách cú pháp with được thực hiện. Tôi thấy rằng nó sử dụng các phương pháp __enter__(self)__exit(self)__. Nhưng tất cả những gì tôi phải làm là triển khai các phương thức đó và tôi có thể sử dụng cú pháp? Hoặc là có nhiều đến nó?

Có một ví dụ về cách thực hiện điều này hoặc một số tài liệu về cách nó được triển khai trên các đối tượng tệp mà tôi có thể xem không?

Trả lời

36

Những phương pháp là khá nhiều tất cả các bạn cần để làm cho đối tượng làm việc với tuyên bố with.

Trong __enter__ bạn phải trả lại đối tượng tệp sau khi mở và thiết lập nó.

Trong __exit__ bạn phải đóng đối tượng tệp. Mã để viết cho nó sẽ nằm trong phần nội dung câu lệnh with.

class Meter(): 
    def __init__(self, dev): 
     self.dev = dev 
    def __enter__(self): 
     #ttysetattr etc goes here before opening and returning the file object 
     self.fd = open(self.dev, MODE) 
     return self.fd 
    def __exit__(self, type, value, traceback): 
     #Exception handling here 
     close(self.fd) 

meter = Meter('dev/tty0') 
with meter as m: 
    #here you work with the file object. 
    m.read() 
+1

'def __enter __ (self): trả về self' nếu bạn muốn tham chiếu đến' Meter' trong khối. – Morgoth

3

Các hit đầu tiên của Google (đối với tôi) giải thích một cách đơn giản đủ:

http://effbot.org/zone/python-with-statement.htm

và PEP giải thích nó một cách chính xác hơn (nhưng cũng một cách chi tiết hơn):

http://www.python.org/dev/peps/pep-0343/

+1

Tôi thực sự đã nhìn thấy những điều đó và không nghĩ rằng một trong số chúng rất rõ ràng. Đầu tiên khá nhiều nói "Có những phương pháp được gọi là \ __ enter__ và \ __ exit__" và giải thích ít hoặc không có gì về chúng. Và PEP khá nhiều chỉ nói về sự cần thiết cho cú pháp mới – Falmarri

+0

Không, nó đơn giản với các ví dụ và giải thích. Bạn cần đọc lại nó; đây không phải là một tính năng phức tạp. –

11

dễ nhất có thể sử dụng tiêu chuẩn Python thư viện mô-đun contextlib:

import contextlib 

@contextlib.contextmanager 
def themeter(name): 
    theobj = Meter(name) 
    yield theobj 
    theobj.close() # or whatever you need to do at exit 

này không làm cho Meter bản thân một người quản lý bối cảnh (và do đó là không xâm lấn đến lớp đó), mà đúng hơn " trang trí "nó ​​(không theo nghĩa của" cú pháp trang trí "của Python, nhưng khá gần, nhưng không hoàn toàn, theo ý nghĩa của mẫu thiết kế trang trí ;-) với chức năng nhà máy themeter; decorator xây dựng từ t chức năng máy phát điện "one- yield" của bạn) - điều này làm cho nó vì vậy dễ dàng hơn để tách điều kiện vào và thoát, tránh làm tổ, & c.

Các vấn đề liên quan