2011-09-27 8 views
30

Sto utilizzando subprocess.check_output dal modulo subprocess pythons per eseguire un comando ping. Ecco come lo faccio:verifica l'output da CalledProcessError

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

Si sta alzando un CalledProcessError e dice l'uscita è uno degli argomenti della funzione. Qualcuno può aiutarmi a leggere quell'output. Mi piacerebbe leggere l'output in una stringa e analizzarlo. Quindi, diciamo per esempio se il ping restituisce

100% di perdita di pacchetti

ho bisogno di catturare questo. Se c'è un altro modo migliore ... si prega di suggerire. Grazie.

+1

//, Vuoi includere un collegamento alla documentazione per questo, https://docs.python.org/2/library/subprocess.html#subprocess.CalledProcessError, in questa domanda? –

risposta

10

Nell'elenco di argomenti, ciascuna voce deve essere autonoma. Utilizzando

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

dovrebbe risolvere il problema.

+0

Ricevo ancora l'errore. L'errore dice che l'output è uno degli argomenti di CalledProcessError. Ho provato a provare, eccetto ... ma non ha funzionato. – ash

+0

@ash Puoi pubblicare un [esempio breve riproducibile] (http://sscce.org/) che dimostra che 'except' non funziona? – phihag

+1

provare: subprocess.check_output (["ping", "-c", "2", "-W", "2", "1.1.1.1") eccetto CalledProcessError come e: print str (e.output). Questo è il mio blocco catch try – ash

127

Secondo lo Python os module documentation os.popen è stato deprecato da Python 2.6.

Penso che la soluzione per Python moderno sia utilizzare check_output() dal modulo subprocess.

Dal subprocess Python documentation:

subprocess.check_output (args, *, stdin = None, stderr = nessuno, shell = false, universal_newlines = False) comando di marcia con argomenti e restituisce la sua uscita come un byte stringa.

Se il codice di ritorno era diverso da zero, genera un errore CalledProcessError. L'oggetto CalledProcessError avrà il codice di ritorno nell'attributo returncode e qualsiasi output nell'attributo output.

Se si esegue attraverso il seguente codice in Python 2.7 (o successiva):

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 

Si dovrebbe vedere un output simile a questa:

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), 

L'e.output la stringa può essere analizzata per soddisfare le esigenze dell'OP.

Se si desidera che il codice di ritorno o altri attributi, sono in CalledProccessError come si può vedere facendo un passo attraverso con PDB

(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'] 
+0

risposta perfetta +1 –

+2

nota: usa 'check_call' invece di' check_output' se non usi l'output. Se si sa che il comando restituisce uno stato di uscita diverso da zero in casi ordinari, si può usare direttamente 'p = Popen()' e chiamare 'p.wait()' o 'output, err = p.communicate()' (se hai bisogno dell'output) per evitare di generare eccezioni inutili – jfs

+0

@JFSebastian Cerco di usare subprocess.call ma questo mi restituisce un int (1) e non l'output del mio comando:/ – Loretta

0

Thanx @krd, sto usando il processo di cattura errori, ma ha dovuto aggiornare la stampa e tranne dichiarazioni. Sto usando Python 2.7.6 su Linux Mint 17.2.

Inoltre, non era chiaro da dove provenisse la stringa di output. mio aggiornamento:

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) 

Vedo un output simile a questo:

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

Se si desidera ottenere stdout e stderr dorsale (compresa estraendolo dal CalledProcessError nel caso in cui uno si verifica), l'uso il seguente:

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

Questo è compatibile con Python 2 e 3.

Se il comando è una stringa piuttosto che un array, prefisso questo con:

import shlex 
command = shlex.split(command) 
0

Ho incontrato lo stesso problema e ha scoperto che il documentation ha esempio di questo tipo di scenario (dove scriviamo STDERR TO STDOUT e uscire sempre correttamente con codice di ritorno 0) senza causare/catturare un'eccezione.

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

Ora, è possibile utilizzare la funzione stringa standard find di verificare la stringa di output output.

Problemi correlati