web-dev-qa-db-de.com

überprüfen Sie die Ausgabe von CalledProcessError

Ich verwende subprocess.check_output vom Modul pythons subprozess, um einen ping-Befehl auszuführen. So mache ich es:

output = subprocess.check_output(["ping","-c 2 -W 2","1.1.1.1")

Es löst einen CalledProcessError aus und sagt, dass die Ausgabe eines der Argumente der Funktion ist. Kann mir jemand helfen, diese Ausgabe zu lesen. Ich möchte die Ausgabe in eine Zeichenfolge einlesen und sie analysieren. Sagen Sie zum Beispiel, wenn der Ping zurückkehrt 

100% Paketverlust

Ich muss das einfangen. Wenn es einen anderen besseren Weg gibt, bitte. Vielen Dank.

38
ash

In der Liste der Argumente muss jeder Eintrag für sich alleine sein. Verwenden

output = subprocess.check_output(["ping", "-c","2", "-W","2", "1.1.1.1"])

sollte dein Problem beheben.

12
phihag

Gemäß der Python os-Moduldokumentation ist os.popen seit Python 2.6 veraltet.

Ich denke, die Lösung für modernes Python ist die Verwendung von check_output () aus dem Subprozess-Modul.

Aus der subprozess-Python-Dokumentation :

subprozess.check_output (args, *, stdin = Keine, stderr = Keine, Shell = False, Universal_newlines = False) Führen Sie den Befehl mit Argumenten aus und geben Sie die Ausgabe als Byte-Zeichenfolge zurück.

Wenn der Rückkehrcode nicht Null war, wird ein CalledProcessError ausgelöst. Das CalledProcessError-Objekt enthält den Rückgabewert im Rückgabecode-Attribut und alle Ausgaben im Ausgabeattribut.

Wenn Sie den folgenden Code in Python 2.7 (oder höher) durchlaufen:

import subprocess

try:
    print subprocess.check_output(["ping", "-n", "2", "-w", "2", "1.1.1.1"])
except subprocess.CalledProcessError, e:
    print "Ping stdout output:\n", e.output

Sie sollten eine Ausgabe sehen, die ungefähr so ​​aussieht:

Ping stdout output:

Pinging 1.1.1.1 with 32 bytes of data:
Request timed out.
Request timed out.

Ping statistics for 1.1.1.1:
Packets: Sent = 2, Received = 0, Lost = 2 (100% loss),

Die e.output-Zeichenfolge kann entsprechend den OP-Anforderungen analysiert werden. 

Wenn Sie den Rückgabecode oder andere Attribute haben möchten, befinden sie sich in CalledProccessError, wie durch das Durchlaufen von pdb angezeigt wird

(Pdb)!dir(e)   

['__class__', '__delattr__', '__dict__', '__doc__', '__format__',
 '__getattribute__', '__getitem__', '__getslice__', '__hash__', '__init__',
 '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
 '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', 
 '__unicode__', '__weakref__', 'args', 'cmd', 'message', 'output', 'returncode']
145
krd

Wenn Sie stdout und stderr zurückerhalten möchten (einschließlich des Extrahierens aus dem CalledProcessError, falls einer auftritt), verwenden Sie Folgendes:

command = ["ls", "-l"]
try:
    output = check_output(command, stderr=STDOUT).decode()
    success = True 
except CalledProcessError as e:
    output = e.output.decode()
    success = False

Dies ist kompatibel mit Python 2 und 3.

Wenn Ihr Befehl eine Zeichenfolge und nicht ein Array ist, stellen Sie Folgendes vor:

import shlex
command = shlex.split(command)
2
Zags

Thanx @krd, ich benutze Ihren Fehler-Catch-Prozess, musste aber die Print- und Except-Anweisungen aktualisieren. Ich verwende Python 2.7.6 unter Linux Mint 17.2.

Es war auch unklar, woher der Ausgabestring von ..__ kam. Mein Update:

import subprocess

# Output returned in error handler
try:
    print("Ping stdout output on success:\n" + 
           subprocess.check_output(["ping", "-c", "2", "-w", "2", "1.1.1.1"]))
except subprocess.CalledProcessError as e:
    print("Ping stdout output on error:\n" + e.output)

# Output returned normally
try:
    print("Ping stdout output on success:\n" + 
           subprocess.check_output(["ping", "-c", "2", "-w", "2", "8.8.8.8"]))
except subprocess.CalledProcessError as e:
    print("Ping stdout output on error:\n" + e.output)

Ich sehe eine Ausgabe wie diese:

Ping stdout output on error:
PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.

--- 1.1.1.1 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 1007ms


Ping stdout output on success:
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=59 time=37.8 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=59 time=38.8 ms

--- 8.8.8.8 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 37.840/38.321/38.802/0.481 ms
0
AndruWitta

Ich bin auf das gleiche Problem gestoßen und habe herausgefunden, dass die Dokumentation ein Beispiel für diese Art von Szenario hat (wo wir STDERR TO STDOUT schreiben und immer erfolgreich mit dem Rückkehrcode 0 beenden), ohne eine Ausnahme zu verursachen/zu fangen.

output = subprocess.check_output("ping -c 2 -W 2 1.1.1.1; exit 0", stderr=subprocess.STDOUT, Shell=True)

Jetzt können Sie die Standardzeichenfolgenfunktion find verwenden, um die Ausgabezeichenfolge output zu überprüfen.

0
Joseph