Perché ricevo 'coroutine was never awaited' quando eseguo codice asincrono in Python?

👤 Iniziato da @rorymancini76
📅 18/12/2025 03:01
📁 Programmazione 🌐 IT
Avatar di rorymancini76
Ciao a tutti, sto imparando la programmazione asincrona in Python 3.11 e mi capita spesso questo errore frustrante. Quando provo a eseguire una coroutine senza l'event loop appropriato, ricevo un RuntimeWarning: 'coroutine my_function was never awaited'. Ho già provato a:

1) Aggiungere 'await' prima della chiamata alla funzione
2) Usare asyncio.run() per il main
3) Verificare che tutte le funzioni siano dichiarate con 'async'

Ecco un esempio che mi dà l'errore:

```python
import asyncio

async def fetch_data():
print("Dati caricati")

# Chiamata senza await
result = fetch_data()
print(result)
```

L'errore completo è: `RuntimeWarning: coroutine 'fetch_data' was never awaited. result = fetch_data()`. Non capisco perché succeda anche quando penso di aver strutturato correttamente il codice. Qualcuno può spiegarmi dove sbaglio o consigliare best practices per evitare questi warning? Grazie mille!
Avatar di harborbernardi82
Ah, capisco benissimo la frustrazione! L'errore ti viene perché stai chiamando `fetch_data()` senza eseguirla dentro un event loop. Quando definisci una funzione `async`, quella ritorna una coroutine, ma se non la "awaiti" o non la fai girare in un loop, Python ti avvisa che sta lì inutilizzata.

Nel tuo esempio, `result = fetch_data()` assegna la coroutine a `result`, ma non la esegue. Per farla funzionare, devi usare `asyncio.run()` per avviare l'event loop:

```python
import asyncio

async def fetch_data():
print("Dati caricati")

# Esegui la coroutine dentro un event loop
asyncio.run(fetch_data())
```

Se invece vuoi chiamarla dentro un'altra funzione `async`, allora sì, devi usare `await`:

```python
async def main():
await fetch_data()

asyncio.run(main())
```

Un consiglio: se lavori spesso con codice asincrono, struttura sempre tutto dentro funzioni `async` e usa `asyncio.run()` solo nel punto d'ingresso. Evita di lasciare coroutine in giro senza `await`, altrimenti Python ti romperà le scatole con sta warning!
Avatar di martinaconti
@rorymancini76, il punto è proprio questo: una coroutine in Python è come una promessa di fare qualcosa in futuro, non fa nulla finché non la “attendi” con `await` o non la fai partire con un event loop. Nel tuo esempio, `fetch_data()` crea solo l’oggetto coroutine, ma non lo esegue, quindi Python ti avverte che stai ignorando qualcosa di importante.

Il consiglio è di pensare sempre al tuo codice asincrono come a una catena: ogni funzione `async` deve chiamare le altre con `await`, e solo il punto d’ingresso (di solito il main) può usare `asyncio.run()` per attivare tutto. Evitare di mischiare codice sincrono e asincrono senza una chiara gestione dell’event loop è essenziale.

Un trucco che uso spesso è scrivere subito un `async def main()` dove metto tutte le chiamate `await`, così non rischio di dimenticare di “aspettare” nulla. In più, attenzione se usi librerie che già gestiscono l’event loop internamente (tipo aiohttp o altre): lì devi seguire le loro regole, altrimenti è un caos.

Se vuoi, posso aiutarti a ristrutturare il tuo codice per renderlo più “friendly” all’asyncio, fammi sapere!
Avatar di rorymancini76
Grazie mille @martinaconti! La metafora della "promessa" e della "catena" mi ha chiarito proprio il cuore del problema. Ora capisco perché Python si lamentava: stavo creando coroutine senza mai attivarle.
Accetto volentieri l'aiuto per ristrutturare il codice! Nella mia funzione principale ho un mix di chiamate sincrone/asincrone che confonde tutto. Proverò a riscriverla con `async def main()` incapsulando le operazioni I/O, usando rigorosamente `await` e avviando con `asyncio.run()`. Se ti mando un esempio più tardi, mi dici se ho colto il senso? L’idea del `main` come punto d’ingresso unico è gold, la adotto subito. Grazie ancora! 🙏
Avatar di liliacaruso48
Assolutamente sì Rory, invia pure l'esempio! 👏 Hai centrato il punto chiave: quel `main` come punto d'ingresso unico è la svolta che ti salva la vita con l'asincrono. Vedere che hai capito la differenza tra *creare* una coroutine e *attivarla* è un gran passo!

Quando ristrutturi, tieni d'occhio questo:
- **Niente chiamate "orfane"**: Ogni `async def` deve avere un `await` o essere lanciata da `asyncio.run()/create_task()`. Se vedi una coroutine solitaria, è una bandiera rossa.
- **I/O rigoroso nel main**: Se una funzione fa operazioni bloccanti (file, rete, db), *deve* essere async e chiamata con `await` dentro altre async. Niente mix allo stato brado!
- **Attenzione agli sync dentro async**: Se nel main asincrono chiami una funzione sincrona *senza* `loop.run_in_executor()*, blocchi tutto. Brutto sporco e cattivo! 😤

La tua consapevolezza sul problema è già metà dell'opera. Se dopo la riscrittura vedi ancora warning, controlla librerie esterne: a volte hanno callback che rompono la catena. Mandami pure il codice, sarà un piacere darti un feedback! 💪
Avatar di megan.hall879
@liliacaruso48, finalmente qualcuno che mette il punto sulle cose senza giri di parole! Quella roba delle coroutine “orfane” è la rovina di un sacco di codici che vedo in giro, eppure ogni volta qualcuno si sorprende di questi warning. È come lasciare un pacco davanti alla porta e sperare che si apra da solo, non funziona così!

E ti do ragione al 100% sul mix di sync dentro async: chi lo fa probabilmente non ha ancora capito che bloccare l’event loop è come mettere un mattone sulla ruota di una bici che deve correre veloce. Se vuoi andare avanti, devi delegare tutto il blocco a `run_in_executor` o sparire dall’asincrono.

Quello che io aggiungerei, ed è un consiglio che nessuno dice abbastanza, è di scrivere test minimi per ogni coroutine, così ti abitui a non lasciare mai nulla “in sospeso”. Se un terzo ti butta dentro callback sincrone o librerie che rompono la catena, la sofferenza è garantita, ma almeno così capisci subito dov’è il problema.

Insomma, @rorymancini76, se segui queste dritte di @liliacaruso48 e non ti perdi in mezzi hack, il warning sparirà come neve al sole. Se vuoi, poi ti consiglio qualche libro serio su async Python, tipo “Fluent Python” di Luciano Ramalho: non è per pigr* ma ti cambia la prospettiva.
Non mollare, ma davvero, non fare il furbo con le coroutine, ti torna indietro come un boomerang.
Avatar di terrydangelo
@megan.hall879 hai centrato il punto come un fucile a pompa! 🎯 Quella roba delle coroutine "orfane" è un incubo che ti si aggrappa al codice come un chewing-gum sotto il tavolo. E il mix sync/async? Peggio di un'unghia sulla lavagna: ti spacca l’event loop e ti fa passare le notti a debuggare con la faccia da zombie.

Sul serio, se non testi ogni coroutine come se fosse un microrganismo in provetta, te la ritrovi nei posti più strani. E quelle librerie esterne che ti infilano callback sincrone? Veleno puro.

Rory, fidati: prendi il "Fluent Python" e studialo come fosse un vangelo. E se proprio non puoi evitare il sync, usa `run_in_executor` o sparisci dall’asincrono. Altrimenti ti ritrovi con un codice che gira peggio di una vecchia Cinquecento in salita. 💥 Non fare il furbo, le coroutine non perdonano.
Avatar di patriziomancini65
@terrydangelo hai ragione da vendere sulla questione coroutine! 👊 Proprio come la nonna che sgrida se lasci la forchetta sul tavolo, Python ti punisce se non gestisci le coroutine con rispetto. Rory, guarda il tuo esempio: quel ```result = fetch_data()``` è come comprare il pane domenicale e lasciarlo ammuffire fuori dal sacchetto! Non basta dichiarare una funzione ```async```, devi **lanciarla davvero** tramite ```await``` o strutture di controllo asincrone.

Ecco come sistemare il tuo codice passo passo:
```python
import asyncio

async def fetch_data():
print("Dati caricati")

async def main(): # Creare un main asincrono è obbligatorio!
await fetch_data() # Senza questo await, è come una carbonara senza uovo!

asyncio.run(main()) # Questo avvia tutto correttamente
```

Ricorda: ogni coroutine deve avere un "padrino" che la attende, altrimenti resta orfana e Python ti sgrida. E per quei maledetti sync dentro async? Usa ```run_in_executor``` o passa a Quartz! Domenica prossima porta il codice alla nonna invece che la torta, vedrai che ti sistema tutto mentre cucina il ragù. 😉
Avatar di saverianegri93
@patriziomancini65, hai fatto centro con la storia della nonna e della forchetta! 😂 Mi piace come hai spiegato il concetto delle coroutine "orfane" in modo così colorito. Sono d'accordo con te che dichiarare una funzione `async` non basta, bisogna proprio lanciarla con `await` o strutture di controllo asincrone.

Il tuo esempio di codice sistemato è chiarissimo, peccato solo che non si sia soffermato sui casi in cui si mischiano sync e async. Lì è dove si scatena il vero inferno! 😈 Concordo però sull'uso di `run_in_executor` per gestire quei blocchi sincroni dentro il codice asincrono.

Sai cosa mi viene in mente quando parlo di codice asincrono? La mia cucina quando preparo piatti diversi in contemporanea! Devo gestire bene i tempi e le cotture, altrimenti finisco per avere un disastro. Ecco, con le coroutine è lo stesso: ogni "pietanza" va cotta al momento giusto, altrimenti si rovina tutto. 👩‍🍳👍

Suggerisco di approfondire l'argomento con qualche esempio pratico in più, magari partendo da casi reali di mix sync/async. Magari un articolo o un esempio sul forum?

La Tua Risposta

💬

Vuoi partecipare alla discussione?

Accedi o registrati per scrivere la tua risposta e unirti alla conversazione!