2010-01-25 4 views
15

Ich verwende das Subprozess Modul, um ein externes Programm (plink.exe) anzumelden, um sich bei einem Server einzuloggen; aber wenn ich call anrufe, um die Ausgabe zu lesen, blockiert es. Der Code ist unten:Python Subprozess communicate() Block

import subprocess 
process = subprocess.Popen('plink.exe [email protected] -pw 123456'.split(), shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 
print process.communicate() #block here 

Ich weiß, dass der Block ist, weil plink.exe es noch läuft; aber ich muss die Ausgabe lesen, bevor der Subprozess beendet wird. Gibt es das überhaupt zu tun?

+0

Haben Sie mit Plink interagieren müssen, oder Sie müssen nur den Anruf tätigen und lesen die Std-Ausgabe ohne Blockierung? – Khelben

+0

verwandt: [Python: Lesen Streaming-Eingabe von Subprozess.communicate()] (http://stackoverflow.com/q/2715847/4279) – jfs

Antwort

26

Der ganze Zweck der communicate Methode ist zu warten, bis der Prozess beendet ist und die gesamte Ausgabe zurückgibt. Wenn Sie nicht warten möchten, rufen Sie nicht communicate. Lesen Sie stattdessen das Attribut stdout oder stderr, um den Ausgang zu lesen.

Wenn der Prozess sowohl an stdout als auch an stderr (und Sie möchten es separat lesen) ausgibt, müssen Sie vorsichtig sein, um tatsächlich von beiden zu lesen, ohne zu blockieren, oder Sie können Deadlock. Unter Windows ist dies ziemlich schwierig, und Sie sollten stattdessen das Modul pexpect verwenden.

+0

'Pexpect' funktioniert nicht auf Windows. [asyncio] (http://stackoverflow.com/a/20697159/4279) oder [threads] (http://stackoverflow.com/a/4896288/4279) könnte verwendet werden, um beide Streams ohne Blockierung zu lesen. – jfs

0

Ich konfrontiert eine ähnliche Situation, wo ich einen einzigen Befehl lmstat -a ausführen musste und dann den Ausgang des Terminals zu bekommen.

Wenn Sie nur einen einzigen Befehl ausgeführt werden müssen und dann die Ausgabe lesen, können Sie den folgenden Code verwenden:

import subprocess 

Username = 'your_username' 
Password = 'your_password' 
IP = 'IP_of_system' 
Connection_type = '-ssh' #can have values -ssh -telnet -rlogin -raw -serial 

p = subprocess.Popen(['plink', Connection_type, '-l', Username, '-pw', Password, IP], \ 
        shell = False, stdin=subprocess.PIPE, stdout=subprocess.PIPE) 
out, err = p.communicate('lmstat -a\nexit\n'.encode()) 
print(out.decode()) 
+1

Wie @Thomas sagte, ist dies eine blockierende und keine blockierungsfreie Methode – Fookatchu