Ich versuche, SIGINT
(oder Tastatur-Interrupt) in Python 2.7 Programm zu fangen. So sieht mein Python-Testscript test
aus:
Weiter Ich habe ein Shell-Skript test.sh
:
Wenn ich das Skript mit bash, sh oder etwas bash test.sh
ausführe, läuft der Python-Prozess test
weiter und kann nicht mit SIGINT
gekillt werden. Wenn ich den Befehl test.sh
kopiere und ihn in (bash) terminal einfüge, wird der Python-Prozess test
beendet.
Ich kann nicht verstehen, was vorgeht, was ich gerne verstehen würde. Also, wo ist der Unterschied und warum?
Hier geht es nicht um wie man SIGINT
in Python fängt! Laut Dokumenten - das ist der Weg, der funktionieren sollte:
Python installiert standardmäßig eine kleine Anzahl von Signalhandlern: SIGPIPE ... und SIGINT wird in eine KeyboardInterrupt-Ausnahme übersetzt
Es fängt tatsächlich KeyboardInterrupt
ein, wenn SIGINT
von kill
gesendet wird, wenn das Programm direkt von der Shell gestartet wird, aber wenn das Programm von bash script im Hintergrund gestartet wird, scheint KeyboardInterrupt
niemals angehoben.
Es gibt einen Fall, in dem der Standard-Sigint-Handler beim Start nicht installiert ist, und das ist, wenn die Signalmaske beim Programmstart SIG_IGN
für SIGINT
enthält. Der dafür zuständige Code kann hier gefunden werden.
Die Signalmaske für ignorierte Signale wird vom übergeordneten Prozess geerbt, während gehandhabte Signale auf SIG_DFL
zurückgesetzt werden. Wenn also SIGINT
ignoriert wurde, wird die Bedingung if (Handlers[SIGINT].func == DefaultHandler)
in der Quelle nicht ausgelöst und der Standard-Handler wird nicht installiert. Python überschreibt in diesem Fall nicht die vom übergeordneten Prozess vorgenommenen Einstellungen.
Versuchen wir nun, den verwendeten Signal-Handler in verschiedenen Situationen zu zeigen:
%Vor% Also wurde im letzten Beispiel SIGINT
auf 1 gesetzt ( SIG_IGN
). Dies ist das gleiche wie beim Starten eines Hintergrundjobs in einem Shell-Skript, da diese standardmäßig nicht interaktiv sind (es sei denn, Sie verwenden die Option -i
im Shebang).
Dies wird dadurch verursacht, dass die Shell das Signal ignoriert, wenn sie einen Hintergrundjob in einer nicht interaktiven Shell-Sitzung startet und nicht direkt mit Python. Mindestens bash
und dash
verhalten sich so, ich habe keine anderen Shells ausprobiert.
Es gibt zwei Möglichkeiten, mit dieser Situation umzugehen:
Installieren Sie den Standard-Signalhandler manuell:
%Vor% Fügen Sie dem shebang des Shell-Skripts die Option -i
hinzu, z. B .:
edit: Dieses Verhalten ist im bash-Handbuch dokumentiert:
SIGNALE
...
Wenn die Jobsteuerung nicht wirksam ist, ignorieren asynchrone Befehle SIGINT und SIGQUIT zusätzlich zu diesen geerbten Handlern.
Dies gilt für nicht interaktive Shells, da die Jobsteuerung standardmäßig deaktiviert ist und tatsächlich in POSIX angegeben ist: Shell-Befehlssprache