2012-12-12 2 views
7

Ich habe versucht zu verstehen, warum das passiert. Ich rufe einen Befehl auf, um das Netzwerk auf Ubuntu Server 12.04 neu zu starten.Python Subprozess check_output viel langsamer als Anruf

Schnelle Ausführung

Als ich rufe Sie den Befehl auf einen der folgenden drei Möglichkeiten, mit Hilfe dauert es etwa 0,1 Sekunden auszuführen:

  1. direkt im Terminal
  2. Python-Skript mit os.system
  3. Python-Skript mit subprocess.call

Terminalsitzung:

[email protected]:~# time /etc/init.d/networking restart 
* Running /etc/init.d/networking restart 
* Reconfiguring network interfaces... 
real 0m0.105s 

[email protected]:~# time python -c "import os; 
> os.system('/etc/init.d/networking restart')" 
* Running /etc/init.d/networking restart 
* Reconfiguring network interfaces... 
real 0m0.111s 

[email protected]:~# time python -c "import subprocess; 
> subprocess.call(['/etc/init.d/networking', 'restart'])" 
* Running /etc/init.d/networking restart 
* Reconfiguring network interfaces... 
real 0m0.111s 

Langsame Ausführung

Allerdings, wenn ich subprocess.check_output oder Popen verwenden und versuchen, die Ausgabe, die es dauert 23 Sekunden gelesen. Viel langsamer. Es scheint, dass dieser dramatische Unterschied nur dann auftritt, wenn ich versuche, eine Funktion zu verwenden, die die Ausgabe der Befehle zurückgibt. Ich würde gerne verstehen, warum dies geschieht und eine Lösung finden, um diesen Befehl auszuführen und seine Ausgabe zu erhalten, ohne dass es so lange dauert.

Terminalsitzung:

[email protected]:~# time python -c "import subprocess; 
> print subprocess.check_output(['/etc/init.d/networking', 'restart'])" 
* Running /etc/init.d/networking restart 
* Reconfiguring network interfaces... 
real 0m23.201s 

[email protected]:~# time python -c "from subprocess import Popen, PIPE; 
> print Popen(['/etc/init.d/networking', 'restart'], stdout=PIPE).stdout.read()" 
* Running /etc/init.d/networking restart 
* Reconfiguring network interfaces... 
real 0m23.201s 

aktualisieren

Einer der Kommentare vorgeschlagen, den Befehl tee auszuprobieren. Die Ergebnisse waren sehr interessant. In dem Terminal ohne Beteiligung von Python, wenn Tee verwendet wird, dauert es die gleichen 23 Sekunden. Ich bin immer noch neugierig, warum, aber das könnte zumindest einen Hinweis darauf geben, was vor sich geht.

[email protected]:~# time /etc/init.d/networking restart | tee out.txt 
* Running /etc/init.d/networking restart 
* Reconfiguring network interfaces... 
real 0m23.181s 
+0

Ich weiß nicht, ob eine der beiden folgenden relevant ist ([Frage # 10150368] (http://stackoverflow.com/questions/10150368/why-is-piping-output-of-subprocess-so -unreliable-with-python), [Frage # 4940607] (http://stackoverflow.com/questions/4940607/python-subprocesses-experience-mysterious-delay-in-receiving-stdin-eof)) aber eine Antwort schlägt vor, hinzuzufügen 'close_fds = True' um Parameter zu öffnen –

+0

' subprocess.call() 'ist nur' subprocess.Popen (* popenargs, ** kwargs) .wait() '. – Blender

+0

@ jwpat7 danke für die Links. Ich habe versucht, close_fds = True, es machte keinen Unterschied. –

Antwort

8

Der folgende Code basiert auf dem hervorragenden Kommentar, den J. F. Sebastian gemacht hat. Der folgende Code wird wie erwartet in 0,1 Sekunden ausgeführt und gibt die Ausgabe des Befehls an eine Zeichenfolge zurück.

from subprocess import check_call, STDOUT 
from tempfile import NamedTemporaryFile 

with NamedTemporaryFile() as f: 
    check_call(['/etc/init.d/networking', 'restart'], stdout=f, stderr=STDOUT) 
    f.seek(0) 
    output = f.read()