Ich habe ein kurzes Bash-Skript foo.sh
Wenn ich es direkt von der Shell aus starte, läuft es gut und wird beendet, wenn es fertig ist
%Vor%aber wenn ich es von Python aus starte
%Vor%Es gibt die Zeile aus, aber dann bleibt es für immer hängen. Was verursacht diese Diskrepanz?
Das Hinzufügen des Befehls trap -p
zum bash-Skript, das Beenden des angehaltenen Python-Prozesses und das Ausführen von ps
zeigt an, was passiert:
Somit führt subprocess.call()
den Befehl mit dem maskierten Signal SIGPIPE
aus. Wenn head
seinen Job ausführt und beendet, erhalten die verbleibenden Prozesse das unterbrochene Pipe-Signal nicht und werden nicht beendet.
Nach der Erklärung des Problems war es leicht, den Fehler im Python-Bugtracker zu finden, der sich als Problem # 1652 herausstellte .
Das Problem mit Python 2, das SIGPIPE
nicht standardgemäß behandelt (dh ignoriert wird), ist bereits in Leons Antwort geprägt, und das Update ist in der Verknüpfung angegeben: set SIGPIPE
auf Standard ( SIG_DFL
) mit zB
Sie können versuchen, SIGPIPE
in Ihrem Skript mit z. B.
aber leider funktioniert es nicht, wie im Bash-Referenzhandbuch
Signale, die beim Eintritt in die Shell ignoriert werden, können nicht abgefangen oder zurückgesetzt werden.
Ein letzter Kommentar: Sie haben eine nutzlose Verwendung von cat
hier; Es ist besser, das Skript wie folgt zu schreiben:
Da Sie jedoch Bash verwenden, können Sie auch das read
builtin wie folgt verwenden (dies wird vorteilhafterweise fold
und head
ersetzen):
Es stellt sich heraus, dass Sie mit dieser Version eine klare Vorstellung davon haben, was vor sich geht (und das Skript wird nicht hängen bleiben):
%Vor% (Natürlich funktioniert es gut ohne Fehler mit Python3). Und Python zu sagen, das Standardsignal für SIGPIPE
zu verwenden, funktioniert auch gut:
(und funktioniert auch mit Python3).
Tags und Links python bash subprocess pipeline