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

В многопоточной программе на Python один поток иногда запрашивает консольный ввод с помощью встроенногосырой ввод(), Я хотел бы иметь возможность закрыть программу, находясь в приглашении 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 вообще (только тот факт, что фоновый поток блокируется, так что соединение не завершается).

Ответы на вопрос(2)

Ваш ответ на вопрос