W wielowątkowym Pythonowego programu jeden wątek czasami prosi wejścia konsoli przy wbudowanej raw_input(). Chciałbym być w stanie zamknąć program przy znaku raw_input, wpisując^C w powłoce (tj. Z sygnałem SIGINT). Jednak gdy wątek potomny wykonuje raw_input, wpisanie^C nic nie robi - Przerwanie klawiatury nie jest wywoływane, dopóki nie uderzę return (pozostawiając raw_input).Przerwanie Pythona raw_input() w wątku dziecko z^C/KeyboardInterrupt
Na przykład, w następującym programie:
import threading
class T(threading.Thread):
def run(self):
x = raw_input()
print x
if __name__ == '__main__':
t = T()
t.start()
t.join()
Wpisanie^C nie robi nic, aż po wejście jest zakończona. Jednakże, jeśli po prostu zadzwonimy pod numer T().run()
(tj. W przypadku pojedynczego wątku: po prostu uruchom raw_input w głównym wątku),^C natychmiast zamknie program.
Można przypuszczać, że to dlatego, że SIGINT wysyłany jest do głównego wątku, który jest zawieszony (czekając na GIL), podczas gdy rozwidlone bloki gwintowania na konsoli czytać. Główny wątek nie wykonuje swojej procedury obsługi sygnału, dopóki nie pobierze GIL po zwróceniu wartości raw_input. (Proszę mnie poprawić, jeśli się mylę - nie jestem ekspertem od implementacji wątków Pythona.)
Czy istnieje sposób odczytu ze standardowego wejścia w sposób raw_input-like, pozwalając na obsługę SIGINT przez główną nić, a tym samym obniżyć cały proces?
[Mam obserwowane zachowanie wyżej na Mac OS X i kilku różnych dystrybucji Linksa.]
Edit: Mam scharakteryzowały podstawowy problem powyżej. W toku dalszych badań jest to wezwanie głównego wątku do join()
, które uniemożliwia obsługę sygnałów: sam Guido van Rossum wyjaśnił, że the underlying lock acquire in join is uninterruptible. Oznacza to, że sygnał jest rzeczywiście odroczone do wykończenia całego wątku - tak naprawdę to nie ma nic wspólnego z raw_input
na wszystkich (tylko fakt, że wątek tło blokuje tak, że połączenie nie zakończy).
Nie łączy się tylko wątków i przerwań ... [boromir.jpg] – JBernardo