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