HOWTO · Python
Chiama programma esterno in Python
Questo tutorial mostra come eseguire programmi esterni in Python
In questa pagina
Per la maggior parte dei normali comandi esterni, usa subprocess.run(). Passa l’eseguibile e i relativi argomenti come elenco, così Python non chiede a una shell di interpretarli. Se ti serve un output leggibile, imposta capture_output=True e text=True, quindi consulta stdout, stderr e returncode nell’oggetto che rappresenta il processo terminato. L’esempio seguente avvia Python stesso, quindi non dipende dalla presenza di un’utilità della shell.
Esegui questo esempio:
Il codice e le etichette o gli output visibili in questa sezione restano in inglese.
import subprocess
import sys
result = subprocess.run(
[sys.executable, "-c", "print('Hello from Python')"],
capture_output=True,
text=True,
check=True,
)
print(result.stdout, end="")
print("Return code:", result.returncode)
Hello from Python
Return code: 0
Un elenco mantiene separati gli argomenti, anche quando uno contiene spazi. text=True decodifica i flussi acquisiti in stringhe usando la codifica testuale della piattaforma; senza questa opzione, stdout e stderr sono byte. check=True fa sì che uno stato del comando diverso da zero sollevi subprocess.CalledProcessError. Omettila se vuoi gestire lo stato autonomamente. L’output acquisito è distinto dallo stato del comando: un comando può scrivere in uno dei due flussi e terminare comunque con un returncode diverso da zero.
Usa os.system() per eseguire un comando della shell
os.system() passa la stringa a un interprete di comandi, che sulle piattaforme più comuni è una shell, e restituisce lo stato dell’interprete. Di norma, l’output standard e l’output di errore del comando restano collegati al processo padre: questa chiamata quindi non ti fornisce testo acquisito. È una scelta legacy per un semplice comando della shell, quando il comportamento della shell è intenzionale. Per passare un elenco di argomenti, acquisire i flussi o gestire lo stato in modo strutturato, preferisci subprocess.run().
Poiché l’input è sintassi della shell, non costruire la stringa inserendovi testo non attendibile: i metacaratteri della shell possono modificare ciò che viene eseguito. L’interprete di comandi esatto e la codifica dello stato variano in base alla piattaforma, quindi non presumere che il valore restituito sia sempre il codice di uscita originale del processo figlio. Per esempio, la chiamata concettuale portabile è os.system("some-command"); scegli un comando concreto e regole di quoting adatte al sistema operativo su cui verrà eseguito.
Usa os.popen() per leggere l’output di un comando
os.popen() apre una pipe verso un comando eseguito tramite una shell e restituisce un oggetto simile a un file. Leggi il flusso e chiudilo al termine; anche close() può fornire lo stato del comando. Questa interfaccia legacy è adatta a interazioni semplici basate su pipe e non offre la gestione separata di stdout e stderr disponibile con subprocess.
La struttura, per esempio, è pipe = os.popen(command), seguita da output = pipe.read() e status = pipe.close(). La shell interpreta la stringa del comando, quindi presta la stessa attenzione agli input non attendibili richiesta da os.system(). Il valore restituito da close() non sostituisce l’output acquisito e la rappresentazione dello stato può dipendere dalla piattaforma. Per il nuovo codice che deve ottenere sia l’output sia un codice di ritorno chiaro, preferisci subprocess.run().
Usa subprocess.Popen() per un controllo più dettagliato del processo
subprocess.Popen() è il costruttore della classe da usare quando un programma deve interagire con un processo mentre è in esecuzione. Per avviare direttamente un programma, passa un elenco di argomenti. Imposta stdout=subprocess.PIPE o stderr=subprocess.PIPE solo se prevedi di leggere quei flussi. Chiama communicate() per raccogliere le pipe configurate e attendere il completamento; se non devi raccogliere output da pipe, puoi chiamare wait().
Leggere manualmente una pipe mentre il processo figlio scrive molto nell’altra può riempire un buffer del sistema operativo e bloccare i processi. communicate() è il modo abituale per raccogliere insieme entrambi i flussi; restituisce byte, a meno che non sia attiva la modalità testo. Per output voluminosi o generati in streaming, gestisci i flussi con attenzione invece di memorizzare tutto in memoria. Se ti basta attendere e controllare il risultato di un processo terminato, subprocess.run() è più semplice.
Usa subprocess.call() per eseguire un comando e attenderne il completamento
subprocess.call() esegue un comando, ne attende il completamento e ne restituisce lo stato. Passa un elenco, per esempio subprocess.call(["program", "--version"]), per evitare l’interpretazione della shell. Questa funzione di utilità non acquisisce l’output per impostazione predefinita: il processo figlio eredita i flussi. Se ti servono i flussi acquisiti, la decodifica del testo o i campi di CompletedProcess, usa subprocess.run(). call() è ancora utile nel codice esistente quando serve soltanto uno stato sincrono, ma in genere il nuovo codice trae vantaggio dall’interfaccia più chiara run().
Uno stato pari a zero indica comunemente un successo, mentre uno diverso da zero segnala che il comando ha riportato un problema. Il significato dei singoli valori diversi da zero dipende dal programma invocato e le convenzioni sugli stati possono variare tra piattaforme. Se vuoi trattare uno stato diverso da zero come un errore, subprocess.run(..., check=True) solleva CalledProcessError; altrimenti controlla returncode e decidi come deve comportarsi la tua applicazione.
Usa subprocess.run() per la maggior parte dei comandi esterni
Per le operazioni comuni, subprocess.run() attende il completamento e restituisce un oggetto CompletedProcess. Con capture_output=True, il risultato contiene stdout e stderr; con text=True, questi valori sono stringhe. L’esempio stampa l’output standard e il codice di ritorno, mentre l’output di errore resta disponibile in result.stderr. Se il programma scrive sull’output di errore, il testo non comparirà in result.stdout.
Per avviare direttamente un programma, preferisci gli elenchi di argomenti e mantieni shell=False, che è l’impostazione predefinita. In questo modo i metacaratteri della shell presenti in un argomento non vengono interpretati come sintassi della shell, anche se il programma di destinazione può comunque comportare rischi legati ai propri input e alla gestione delle opzioni. Usa shell=True solo quando ti servono funzioni della shell, come pipe o redirezioni; in tal caso, mantieni fisso il comando della shell oppure costruiscilo con regole di quoting accurate e adatte alla piattaforma. Un elenco di argomenti è la scelta portabile predefinita, ma i nomi degli eseguibili e le opzioni della riga di comando variano comunque tra sistemi operativi.
Quando un comando non riesce, scegli come gestire il risultato: usa check=True per interrompere l’esecuzione con CalledProcessError, oppure lascialo disattivato e prendi una decisione in base a result.returncode. Se l’eseguibile non esiste o non è possibile avviare il processo, si verifica un errore del sistema operativo prima che sia disponibile un risultato relativo a un processo terminato. Non dedurre il successo dal solo testo dell’output: controlla lo stato e, quando serve, esamina entrambi i flussi.
Conclusione
Per la maggior parte dei comandi esterni, usa subprocess.run(): mantiene separati gli argomenti, attende il processo e fornisce un risultato con lo stato e gli eventuali flussi acquisiti. Usa subprocess.Popen() quando ti serve un controllo più dettagliato mentre il processo è in esecuzione. subprocess.call() è una semplice funzione di utilità sincrona che restituisce solo lo stato. os.system() e os.popen() sono interfacce legacy basate sulla shell: sceglile solo quando il loro comportamento è adatto all’attività. Fornisci alla shell solo input attendibili, acquisisci soltanto i flussi necessari e considera le differenze tra piattaforme nei nomi degli eseguibili e nelle convenzioni sugli stati.