Python: subprocess.call defekte Pipe

8

Ich versuche, ein Shell-Skript in Python aufzurufen, aber es meldet gebrochenen Pipefehler (das Ergebnis ist OK, aber ich möchte die Fehlermeldung nicht in STDERR sehen). Ich habe die Ursache ermittelt und sie kann wie folgt reproduziert werden:

subprocess.call('cat /dev/zero | head -c 10 | base64', shell=True)

AAAAAAAAAAAAAA ==

cat: Schreibfehler: Broken pipe

/dev/zero ist ein unendlicher Stream, aber die head -c 10 liest nur 10 Bytes davon und endet, dann wird cat SIGPIPE bekommen, weil der Peer die Pipe geschlossen hat. Es gibt keine gebrochene Rohr-Fehlermeldung, wenn ich den Befehl in der Shell ausführe, aber warum Python es zeigt?

    
Dagang 07.05.2012, 09:40
quelle

2 Antworten

6

Die Standardaktion für das SIGPIPE-Signal besteht darin, das Programm zu beenden. Der Python-Interpreter ändert es in SIG_IGN, um gebrochene Rohrleitungsfehler in Form von Ausnahmen an ein Programm melden zu können.

Wenn Sie cat ... |head ... in der Shell ausführen, hat cat den standardmäßigen SIGPIPE-Handler und der Betriebssystemkernel beendet ihn nur auf SIGPIPE.

Wenn Sie cat mit subprocess ausführen, wird der SIGPIPE-Handler vom übergeordneten (Python-Interpreter) abgeleitet, SIGPIPE wird ignoriert und cat behandelt den Fehler selbst, indem er errno variable prüft und eine Fehlermeldung ausgibt.

Um Fehlermeldungen von cat zu vermeiden, können Sie preexec_fn Argument für subprocess.call verwenden:

%Vor%     
subdir 16.09.2012 21:58
quelle
2

In diesem trivialen Fall gewinnst du zumindest nichts mit Shell-Befehlen - und du verlierst Portabilität und Geschwindigkeit.

Python 2-Code:

%Vor%

In Python 3 (Code wird auch in 2.6+ ausgeführt, obwohl er str anstatt bytes Instanzen zurückgibt):

%Vor%

In jedem Fall behält das erste Beispiel die Verwendung von /dev/zero (an sich nicht tragbar, aber egal), die zweite erzeugt den Effekt, obwohl ich mir vorstelle, dass es nicht genau das ist, was Sie wollen?

    
Chris Morgan 07.05.2012 10:30
quelle

Tags und Links