2014-09-03 31 views
45

CPython có một hành vi lạ khi nó đặt mô-đun thành Không trong khi tắt máy. Điều này vít lên đăng nhập lỗi trong quá trình tắt của một số mã đa luồng tôi đã viết.Thủ tục tắt của Python được ghi lại ở đâu?

Tôi không thể tìm thấy bất kỳ tài liệu nào về hành vi này. Nó được đề cập khi đi qua trong PEP 432:

[...] giảm đáng kể số lượng mô-đun sẽ được sử dụng để cố ý phá vỡ chu kỳ phá vỡ và cố gắng giải phóng thêm tài nguyên bên ngoài sạch sẽ.

SO questions about this behaviourC API documentation mentions shutdown behaviour for embedded interpreters.

Tôi cũng đã tìm thấy một related thread on python-devrelated CPython bug:

vá này không làm thay đổi hành vi của mô-đun đối tượng thanh toán bù trừ globals của họ từ điển càng sớm càng họ đang deallocated.

Hành vi này được ghi lại ở đâu? Có Python 2 cụ thể?

Trả lời

58

Hành vi này là không cũng ghi nhận, và hiện diện trong tất cả các phiên bản của Python từ khoảng 1,5-ish cho đến khi Python 3.4:

Là một phần của sự thay đổi này, mô-đun globals không còn buộc phải thiết lập đến None trong khi tắt thông dịch trong hầu hết các trường hợp, thay vào đó dựa vào hoạt động bình thường của bộ thu gom rác tuần hoàn.

Tài liệu duy nhất cho hành vi này là moduleobject.c source code:

/* To make the execution order of destructors for global 
    objects a bit more predictable, we first zap all objects 
    whose name starts with a single underscore, before we clear 
    the entire dictionary. We zap them by replacing them with 
    None, rather than deleting them from the dictionary, to 
    avoid rehashing the dictionary (to some extent). */ 

Lưu ý rằng thiết lập các giá trị để None là một tối ưu hóa; thay thế sẽ là xóa tên khỏi ánh xạ, điều này sẽ dẫn đến các lỗi khác nhau (NameError ngoại lệ thay vì AttributeError khi cố gắng sử dụng hình cầu từ trình xử lý __del__).

Như bạn đã tìm thấy trên danh sách gửi thư, hành vi này có trước bộ thu gom rác tuần hoàn; nó là added in 1998, trong khi bộ thu gom rác theo chu kỳ là added in 2000. Vì các đối tượng hàm luôn tham chiếu đến mô-đun __dict__ tất cả các đối tượng chức năng trong một mô-đun liên quan đến tham chiếu vòng tròn, đó là lý do tại sao cần xóa thanh toán __dict__ trước khi GC được phát.

Nó được giữ nguyên ngay cả khi GC tuần hoàn đã được thêm vào, vì có thể có các đối tượng với các phương thức __del__ liên quan đến chu trình. Những aren't otherwise garbage-collectable và làm sạch từ điển mô-đun này ít nhất sẽ xóa mô-đun __dict__ khỏi các chu kỳ như vậy. Không thực hiện điều đó sẽ giữ cho tất cả các hình cầu được tham chiếu của mô-đun đó còn sống.

Những thay đổi được thực hiện cho PEP 442 bây giờ làm cho nó có thể cho các bộ thu rác để xóa tài liệu tham khảo theo chu kỳ với các đối tượng cung cấp một finalizer __del__, loại bỏ sự cần thiết phải xóa module __dict__cho hầu hết các trường hợp. Mã này là still there nhưng điều này chỉ được kích hoạt nếu thuộc tính __dict__ vẫn còn hoạt động ngay cả sau khi di chuyển nội dung của sys.modules đến tham chiếu yếu và bắt đầu chạy bộ sưu tập GC khi trình thông dịch tắt; trình phân tích mô-đun chỉ đơn giản là giảm số lượng tham chiếu của chúng.

0

Có một số lượng nhỏ các tài liệu liên quan tại bottom of the threading docs:

Thứ hai, tất cả những nỗ lực nhập khẩu phải được hoàn tất trước khi người phiên dịch bắt đầu đóng chính nó xuống. [..] Việc không chấp hành hạn chế này sẽ dẫn đến các trường hợp ngoại lệ gián đoạn và bị treo trong khi tắt thông dịch viên (vì việc nhập khẩu trễ truy cập vào máy móc không còn ở trạng thái hợp lệ).

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