Прерывание Python raw_input () в дочернем потоке с помощью ^ C / KeyboardInterrupt

В многопоточной программе Python один поток иногда запрашивает ввод консоли с помощью встроенного raw_input ( ) . Я хотел бы иметь возможность закрыть программу в приглашении raw_input, набрав ^ C в оболочке (то есть с сигналом SIGINT). Однако, когда дочерний поток выполняет raw_input, ввод ^ C ничего не делает - KeyboardInterrupt не возникает, пока я не нажму return (оставив raw_input).

Например, в следующей программе:

import threading

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

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

При нажатии ^ C ничего не происходит до тех пор, пока ввод не будет завершен. Однако, если мы просто вызываем T (). Run () (то есть однопоточный случай: просто запускаем raw_input в основном потоке), ^ ​​C немедленно закрывает программу.

Предположительно, это связано с тем, что SIGINT отправляется в основной поток, который приостанавливается (ожидает GIL), пока разветвленный поток блокируется при чтении консоли. Основной поток не может выполнить свой обработчик сигналов, пока он не захватит GIL после возврата raw_input. (Пожалуйста, поправьте меня, если я ошибаюсь - я не эксперт по реализации потоковой передачи Python.)

Есть ли способ читать из stdin в стиле raw_input, позволяя обрабатывать SIGINT с помощью основной поток и тем самым обрушить весь процесс?

[Я наблюдал описанное выше поведение в Mac OS X и нескольких различных Linux.]


Редактировать: Я неправильно охарактеризовал основную проблему выше. При дальнейшем исследовании обнаруживается, что вызов основного потока join () предотвращает обработку сигналов: сам Гвидо ван Россум объяснил, что базовая блокировка в соединении является непрерывной . Это означает, что сигнал фактически откладывается до тех пор, пока не завершится весь поток - так что на самом деле это не имеет ничего общего с raw_input вообще (просто тот факт, что фоновый поток блокируется, так что соединение не завершается ).

8
задан adrian 15 February 2012 в 01:41
поделиться