2012-02-13 29 views
5

Trong chương trình Python đa luồng, một luồng đôi khi yêu cầu đầu vào bảng điều khiển bằng cách sử dụng được xây dựng trong raw_input(). Tôi muốn có thể đóng chương trình trong khi tại dấu nhắc raw_input bằng cách gõ^C vào vỏ (tức là, với tín hiệu SIGINT). Tuy nhiên, khi thread con đang thực thi raw_input, gõ^C không làm gì cả - KeyboardInterrupt không được nâng lên cho đến khi tôi nhấn return (để lại raw_input).Ngắt Python raw_input() trong một chuỗi con với^C/KeyboardInterrupt

Ví dụ, trong các chương trình sau đây:

import threading 

class T(threading.Thread): 
    def run(self): 
     x = raw_input() 
     print x 

if __name__ == '__main__': 
    t = T() 
    t.start() 
    t.join() 

Typing^C không có gì cho đến sau khi đầu vào là xong. Tuy nhiên, nếu chúng tôi chỉ gọi T().run() (nghĩa là trường hợp chỉ có một luồng: chỉ cần chạy raw_input trong chuỗi chính),^C sẽ đóng chương trình ngay lập tức.

Có lẽ, điều này là do SIGINT được gửi đến chủ đề chính, bị treo (chờ GIL) trong khi các chuỗi được chia nhỏ trên bàn điều khiển đọc. Các chủ đề chính không nhận được để thực hiện xử lý tín hiệu của nó cho đến khi nó lấy GIL sau khi raw_input trả về. (Xin vui lòng sửa tôi nếu tôi sai về điều này - Tôi không phải là chuyên gia về việc triển khai luồng của Python.)

Có cách nào để đọc từ stdin theo cách giống như raw_input trong khi cho phép xử lý SIGINT bởi sợi chính và do đó làm giảm toàn bộ quá trình?

[Tôi đã quan sát hành vi nêu trên Mac OS X và một vài Linuxes khác nhau.]


Edit: Tôi đã mischaracterized vấn đề cơ bản ở trên. Khi điều tra thêm, đó là lời kêu gọi của chủ đề chính tới join() đang ngăn chặn việc xử lý tín hiệu: chính Guido van Rossum đã giải thích rằng the underlying lock acquire in join is uninterruptible. Điều này có nghĩa là tín hiệu thực sự bị trì hoãn cho đến khi toàn bộ chuỗi kết thúc - vì vậy điều này thực sự không liên quan gì đến raw_input (chỉ thực tế là luồng nền đang chặn để kết nối không hoàn thành).

+3

Không chỉ đơn giản là kết hợp Chủ đề và gián đoạn ... [boromir.jpg] – JBernardo

Trả lời

0

Thực sự không có cách nào dễ dàng trong khoảng thời gian này.

Một cách tiếp cận là sắp xếp lại và chia nhỏ mã theo cách mà các phần chức năng cần Ctrl-C khả năng gián đoạn được thực hiện trên chuỗi chính. Bạn sử dụng hàng đợi để gửi các yêu cầu thực hiện và tương tự như vậy cho các giá trị kết quả. Bạn cần một hàng đợi đầu vào cho luồng chính và một hàng đợi đầu ra cho mỗi luồng không chính; và một lối thoát luồng chính được phối hợp. Rõ ràng, chỉ có một chức năng chặn được thực hiện tại bất kỳ thời điểm nào theo cách này, có thể không phải là những gì bạn muốn.

Here's a working example of this idea với việc sử dụng sai các ẩn dụ cho phép thoát luồng chính được phối hợp.

3

Khi tham gia được gọi là không có thời gian chờ, nó là không thể ngắt quãng, nhưng khi nó được gọi với một thời gian chờ, nó là gián đoạn. Hãy thử thêm một thời gian chờ tùy ý và đặt nó trong một vòng lặp while:

while my_thread.isAlive(): 
    my_thread.join(5.0)