2010-08-10 29 views
15

UPDATE: Để dễ đọc, ở đây là làm thế nào để thêm một callback trước khi lò phản ứng bị tắt máy:xoắn: catch KeyboardInterrupt và tắt máy đúng

reactor.addSystemEventTrigger('before', 'shutdown', callable) 

gốc câu hỏi sau.


Nếu tôi có một khách hàng kết nối với một máy chủ, và nó lạnh trong vòng lặp chính lò phản ứng chờ đợi cho các sự kiện, khi tôi nhấn CTRL-C, tôi nhận được một kết nối "sang phía bên kia đã bị mất trong một tổ chức phi -clean thời trang: Mất kết nối. " Làm thế nào tôi có thể thiết lập nó để tôi biết khi một KeyboardInterrupt xảy ra, để tôi có thể làm sạch thích hợp và ngắt kết nối sạch? Hoặc làm thế nào tôi có thể thực hiện một cách sạch hơn để tắt máy mà không liên quan đến CTRL-C, nếu có thể?

+0

ngọt ngào, lần đầu tiên nhấn vào googling "xoắn trước khi tắt máy"! – Claudiu

Trả lời

29

Nếu bạn thực sự muốn bắt C-c cụ thể, thì bạn có thể thực hiện điều này theo cách thông thường cho ứng dụng Python - sử dụng signal.signal để cài đặt trình xử lý SIGINT làm bất cứ điều gì bạn muốn. Nếu bạn gọi bất kỳ API xoắn nào từ trình xử lý, hãy đảm bảo bạn sử dụng reactor.callFromThread vì hầu như tất cả các API được xoắn khác không an toàn để gọi từ trình xử lý tín hiệu.

Tuy nhiên, nếu bạn thực sự chỉ quan tâm đến việc chèn một số mã dọn dẹp thời gian ngừng hoạt động, thì có thể bạn muốn sử dụng IService.stopService (hoặc cơ chế theo đó nó được triển khai, reactor.addSystemEventTrigger) thay thế.

Nếu bạn đang sử dụng twistd, sau đó sử dụng IService.stopService thật dễ dàng. Bạn đã có đối tượng Application với ít nhất một dịch vụ được đính kèm với nó. Bạn có thể thêm một số khác với phương thức tùy chỉnh stopService để tắt máy của bạn. Phương thức này được phép trả về một số Deferred. Nếu có, thì quá trình tắt máy sẽ bị tạm dừng cho đến khi xảy ra vụ nổ Deferred. Điều này cho phép bạn dọn dẹp các kết nối của mình một cách độc đáo, ngay cả khi có liên quan đến một số hoạt động mạng (hoặc bất kỳ hoạt động không đồng bộ) nào khác.

Nếu bạn không sử dụng twistd, sau đó sử dụng trực tiếp reactor.addSystemEventTrigger có lẽ dễ dàng hơn. Bạn có thể cài đặt trước khi tắt máy kích hoạt sẽ được gọi trong cùng một trường hợp IService.stopService sẽ được gọi. Trình kích hoạt này (chỉ bất kỳ đối tượng có thể gọi) nào cũng có thể trả lại Deferred để trì hoãn tắt máy. Điều này được thực hiện với một cuộc gọi đến reactor.addSystemEventTrigger('before', 'shutdown', callable) (đôi khi trước khi tắt máy được khởi động, do đó nó đã được đăng ký bất cứ khi nào tắt máy xảy ra).

service.tac cung cấp ví dụ về cách tạo và sử dụng dịch vụ tùy chỉnh.

wxacceptance.py đưa ra ví dụ về việc sử dụng addSystemEventTrigger và trì hoãn tắt máy bằng (tùy ý) ba giây.

Cả hai cơ chế này sẽ cung cấp cho bạn thông báo bất cứ khi nào lò phản ứng dừng lại. Điều này có thể là do một phím tắt C-c, hoặc có thể do ai đó sử dụng kill -INT ... hoặc có thể do một nơi nào đó gọi là reactor.stop(). Tất cả đều dẫn đến tắt lò phản ứng, và tắt lò phản ứng luôn xử lý các sự cố tắt máy.

+0

+1 - Không biết về trả chậm! – MattH

+0

hoàn hảo! làm việc giống như tôi thích. bây giờ sau nhiều tháng dọn dẹp xấu xí thì cuối cùng cũng đẹp và đẹp ... – Claudiu

1

Tôi không chắc chắn liệu bạn có nói về khách hàng hay máy chủ mà bạn đã viết hay không.

Dù sao, không có gì sai với 'CTRL-C'.

Nếu bạn đang viết máy chủ làm Ứng dụng. Phân lớp từ twisted.application.service.Service và xác định startServicestopService. Duy trì danh sách các cá thể giao thức đang hoạt động. Sử dụng stopService để xem qua chúng và đóng chúng một cách duyên dáng.

Nếu bạn có khách hàng, bạn cũng có thể phân lớp Service, nhưng có thể đơn giản hơn để sử dụng reactor.addSystemEventTrigger('before','shutdown',myCleanUpFunction) và kết nối chặt chẽ (s) một cách duyên dáng trong chức năng này.