2011-12-21 34 views
5

Tôi đang sử dụng một __del__() của đối tượng để bỏ đăng ký nó từ một sự kiện (sử dụng một chương trình sự kiện tương tự như this):Không thể tham khảo một module nhập khẩu __del __()

import my_enviroment 
class MyClass(): 
    def __del__(self): 
     my_environment.events.my_event -= self.event_handler_func 

Nhưng kỳ lạ tôi nhận được lỗi sau tại khi kết thúc chương trình chạy:

Exception AttributeError: "'NoneType' object has no attribute 'events'" in <bound method MyClass.__del__ of <myclass.MyClass instance at 0x04C54580>> ignored 

Làm sao điều này có thể xảy ra ?! my_environment là một mô-đun tôi đã nhập, làm thế nào đến nó có thể là Không? (events là một đối tượng toàn cầu trong đó có sự kiện móc như my_event)

+0

Điều này thường được gọi như thế nào (ngoài việc chấm dứt chương trình)? Liệu trình xử lý sự kiện có giữ một tham chiếu đến đối tượng sẽ ngăn không cho nó bị thu gom rác không? – interjay

+0

@interjay - Một số đối tượng MyClass sống trong suốt thời gian chạy và một số ngắn ngủi. Tôi đã thêm sự kiện dọn dẹp này cho trường hợp sau này. – Jonathan

+1

Điểm của tôi là điều này sẽ không bao giờ được gọi cho các đối tượng ngắn ngủi vì trình xử lý sự kiện giữ một tham chiếu đến chúng. – interjay

Trả lời

7

Theo python doc about __del__:

[...] globals khác được tham chiếu theo phương pháp __del__() có thể đã bị xóa hoặc trong quá trình bị rách (ví dụ nhập máy tắt máy). Vì lý do này, các phương pháp __del__() nên làm mức tối thiểu tuyệt đối cần thiết để duy trì các bất biến bên ngoài.

Nói cách khác, khi các phương pháp __del__ được gọi trên đối tượng của bạn, my_enviroment có thể được 'xóa' bằng python, vì vậy nó có thể được Không ...

3

Nếu bạn kiểm tra tài liệu Python, bạn sẽ thấy rằng khi các đối tượng được chấm dứt, ở cuối chương trình, "máy móc" đã được tháo rời. Điều đó có nghĩa rằng phần lớn những gì bạn muốn dựa vào đã biến mất - trong trường hợp này, biến toàn cục với tham chiếu mô-đun.

gì bạn phải làm là một trong hai đối tượng của bạn đảm bảo rằng cần phải có __del__ gọi là bị phá hủy trước khi chương trình kết thúc - nhưng vẫn tốt hơn, làm cho các nhà quản lý thì bối cảnh, với __enter____exit__ phương pháp, và sử dụng sau đó trong vòng with báo cáo. Hoặc chỉ quấn các mệnh đề của bạn trong các khối __del__ trong các khối try-except để chúng không tăng ngoại lệ - nếu việc thực thi mã trong đó không quan trọng khi chương trình kết thúc.

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