# Python subprocess: esecuzione di comandi e programmi esterni

Il modulo Python `subprocess` ti consente di controllare, eseguire e valutare programmi esterni all’interno del codice. Le due funzioni più importanti di questo strumento sono `run()` e `Popen()`.

## Che cos’è Python `subprocess`?

Il modulo Python `subprocess` fa parte dell’inventario di questo [linguaggio di programmazione](https://www.ionos.it/digitalguide/siti-web/programmazione-del-sito-web/linguaggi-programmazione-web/) a partire dalla versione 2.4. È uno strumento molto completo e potente che puoi utilizzare per **eseguire altri programmi o comandi all’interno del tuo codice**. Non soltanto ti permette di aprire i programmi, ma anche di controllare e gestire il flusso di dati. Il modulo `subprocess` di Python offre numerosi metodi e funzioni: in questo articolo esamineremo i più importanti, spiegandoli per mezzo di alcuni esempi pratici.

## Il funzionamento di `subprocess` con `run()`

Per prima cosa è utile dare un’occhiata alla struttura e alle funzionalità di base del modulo `subprocess` di Python. Questo modulo è utilizzato per eseguire sottoprocessi. Python funziona secondo la gerarchia genitore-figlio (parent-child) **con una parte sovraordinata (processo genitore)** che genera un processo subordinato. La funzione utilizzata più spesso all’interno del modulo è `run()`. Essa consente di avviare un processo tramite Python e di dare inizio ai passaggi successivi solo dopo aver completato tale processo.

### Esempio di funzionamento di Python `subprocess` con `run()`

Utilizziamo ora questa funzione per il nostro primo semplice esempio, che ci permette di illustrare il funzionamento di `subprocess` in Python. A tal fine, importiamo prima i moduli `subprocess` e `sys`, quindi eseguiamo una semplice richiesta. Il relativo codice si presenta così:

```python
import subprocess
import sys
result = subprocess.run([sys.executable, "-c", "print('ciao')"])
```

L’output è quindi il seguente:

```python
ciao
```

- `subprocess.run`: questa è la funzione vera e propria. Essa riceve un elenco di stringhe contenenti il comando da eseguire. Successivamente, `run()` esegue un nuovo programma Python.
- `sys.executable`: con `sys.executable` si indica il percorso assoluto che porta al file Python utilizzato in origine per richiamare il programma. Tale percorso può essere ad esempio simile a questo: `/local/utente/bin/esempio`.
- `-c`: `-c` è un’opzione da riga di comando che comunica la stringa specificata per l’esecuzione. Nel nostro esempio si tratta di un programma che emette la parola “ciao”.

## Esecuzione di Python `subprocess` con uno script

Per sperimentare l’uso del modulo per uno script personalizzato, puoi provare il seguente esempio. A tal fine, crea prima un semplice script in formato *.py* e salvalo come “esempioscript.py”:

```python
print("Oggi è una bella giornata")
```

Ora utilizza il codice seguente per eseguire questo file con `subprocess` in Python:

```python
import subprocess
result = subprocess.run(["python", "esempioscript.py"], capture_output=True, text=True)
print(result.stdout)
```

Il risultato che otteniamo si presenta così:

```python
Oggi è una bella giornata
```

## Apertura di programmi esterni

In generale, l’uso di `subprocess` in Python e della funzione `run()` permette di **aprire qualsiasi programma**. L’unico requisito è che tu conosca il nome esatto o il percorso in cui questo programma si trova sul tuo sistema. Ad esempio, nel codice seguente apriamo il Blocco note (Notepad):

```python
import subprocess
subprocess.run(["notepad"])
```

## `CompletedProcess` e acquisizione di output esterni

Dopo questi semplici esempi, passiamo ora a esaminare l’**acquisizione di un output esterno**. A tal fine eseguiamo un programma esterno con `subprocess` di Python come nell’esempio precedente, ma chiediamo al sistema di restituire un cosiddetto oggetto `CompletedProcess`. Le modifiche necessarie sono già presenti in un esempio precedente, ma ora passiamo ad analizzarle più in dettaglio. Il punto di partenza è ancora una volta il nostro primo codice. Ora lo modifichiamo come segue:

```python
import subprocess
import sys
result = subprocess.run([sys.executable, "-c", "print('ciao')"], capture_output=True, text=True)
print("L'output standard è:", result.stdout)
print("Questo è l'errore standard:", result.stderr)
```

Anche questa volta chiediamo al sistema di emettere la stringa di caratteri “ciao”. Questa operazione avviene in un processo subordinato. Tuttavia sono presenti i due nuovi argomenti chiave `capture_output=True` e `text=True`, che assegniamo a `run()`. Se l’istruzione viene eseguita e non restituisce errori, ottieni un oggetto `CompletedProcess` con un collegamento a `result`. L’oggetto contiene informazioni sul codice di uscita del programma che desideri eseguire e le trasmette a `result.stdout` e `result.stderr`. `stdout` contraddistingue l’output standard, mentre `stderr` indica i possibili errori standard. Inoltre, `text=True` serve a stampare l’output sotto forma di stringa. Poiché non è previsto alcun errore standard, il risultato che otteniamo è il seguente:

```python
L'output standard è: ciao
Questo è l'errore standard:
```

Per illustrare il funzionamento, nel prossimo esempio facciamo in modo che questa volta `stderr` non resti vuoto. Il codice da utilizzare è il seguente:

```python
import subprocess
import sys
result = subprocess.run([sys.executable, "-c", "raise ValueError('errore')"], capture_output=True, text=True)
print("L'output standard è:", result.stdout)
print("Questo è l'errore standard:", result.stderr)
```

Mentre questa volta l’output standard rimane vuoto, è ora presente un output per `stderr`:

```python
L'output standard è:
Questo è l'errore standard: Traceback (most recent call last):
	File "<string>", line 1, in <module>
ValueError: errore
```

## Esecuzione di una funzione

Il modulo `subprocess` in Python ti permette anche di **integrare un comando direttamente nel codice**. In questo caso il codice potrebbe presentarsi come in questo esempio:

```python
import subprocess
result = subprocess.run(["C:/Utenti/nome/anaconda3/python", "-c", "print('Questo output è stato preso direttamente da una funzione')"], capture_output=True, text=True, shell=True)
print("L'output standard è:", result.stdout)
```

L’output che otteniamo si presenta così:

```python
L'output standard è: Questo output è stato preso direttamente da una funzione
```

## Interruzione o conclusione di processi

Un’altra applicazione molto utile di `subprocess` in Python è tramite l’interazione tra `run()` e l’argomento `timeout`. In questo modo puoi interrompere un programma esterno se la sua esecuzione impiega troppo tempo. A tal fine si utilizza la funzione `time.sleep`. Il relativo codice è l seguente:

```python
import subprocess
import sys
result = subprocess.run([sys.executable, "-c", "import time; time.sleep(3)"], timeout=1)
```

Il processo subordinato utilizza `time.sleep` per una sospensione di tre secondi. Tuttavia, poiché hai indicato al sistema di far partire un timeout dopo un secondo con `timeout=1`, il risultato è un’eccezione `TimeoutExpired`.

## Python `subprocess` con `Popen()`

Sebbene run() sia la funzione di Python `subprocess` usata più spesso, esistono anche altre importanti [classi](https://www.ionos.it/digitalguide/siti-web/programmazione-del-sito-web/classi-in-python/) che possono esserti molto utili. Tra queste vi è anche `Popen()`. Questa classe è in un certo senso la struttura alla base di `subprocess` in Python ed è un po’ più complessa da usare rispetto a `run()`. Tuttavia, `Popen()` ti offre un maggiore controllo sull’esecuzione e può interagire con input e output. La classe deve il suo nome a un comando UNIX e sta per “pipe open”.

Quasi tutti gli argomenti che puoi utilizzare con `run()` sono consentiti anche con `Popen()` . A differenza di `run()`, questa funzione non attende il completamento di un processo, ma ne **avvia un secondo in parallelo**. È possibile illustrare il funzionamento con un semplice esempio:

```python
import subprocess
from time import sleep
def poll_and_read(process):
    print(f"Questo è l'output dopo poll(): {process.poll()}")
    print(f"Questo è l'output standard: {process.stdout.read().decode('utf-8')}")
process = subprocess.Popen(["python", "timer.py", "3"], stdout=subprocess.PIPE)
poll_and_read(process)
sleep(2)
poll_and_read(process)
sleep(2)
poll_and_read(process)
process.wait()
print(f"Codice di uscita del processo: {process.returncode}")
```

Qui utilizziamo il **metodo `.poll()`** per verificare se il processo è ancora in esecuzione o se è già stato completato. Finché è ancora in esecuzione, viene emesso il valore “none”. Successivamente, il metodo restituisce il codice di uscita. Con `.read()` devono essere letti tutti i byte che si trovano attualmente in `.stdout`. Eseguendo il codice, si ottiene prima il valore “None”, quindi il valore attualmente contenuto in `stdout`. La procedura continua fino al completamento del processo. Infine, `poll()` acquisisce il valore “0”.

Consiglio Deployment di app e siti web direttamente con GitHub: con [Deploy Now](https://www.ionos.it/hosting/deploy-now "Deploy Now di IONOS") di IONOS puoi trarre vantaggio da una configurazione più rapida, flussi di lavoro ottimizzati ed eccellente scalabilità. Trova il piano più adatto alle tue esigenze.


This is a markdown version of: [https://www.ionos.it/digitalguide/siti-web/programmazione-del-sito-web/python-subprocess/](https://www.ionos.it/digitalguide/siti-web/programmazione-del-sito-web/python-subprocess/) for AI/LLM consumption.