RuntimeWarning: coroutine was never awaited — DedSec Project
RuntimeWarning: coroutine was never awaited Τι δημιουργήθηκε; Η κλήση async def επιστρέφει coroutine object· δεν περιμένει την ολοκλήρωσή του. Αν χαθεί χωρίς await ή scheduling, η Python…
Τι δημιουργήθηκε;
Η κλήση async def επιστρέφει coroutine object· δεν περιμένει την ολοκλήρωσή του. Αν χαθεί χωρίς await ή scheduling, η Python μπορεί να εμφανίσει warning όταν καθαρίζεται το object.
import asyncio
async def retrieve():
await asyncio.sleep(0)
return 42
# wrong = retrieve() # δεν έγινε await
result = asyncio.run(retrieve())
assert result == 42
Σεβασμός στο υπάρχον event loop
Μέσα σε async συνάρτηση χρησιμοποίησε await retrieve(). Σε συγχρονικό CLI χωρίς event loop μπορείς να χρησιμοποιήσεις asyncio.run. Σε notebook ή running async application μην εμφωλεύεις asyncio.run: χρησιμοποίησε το υπάρχον loop.
async def combined():
first = await retrieve()
second = await retrieve()
return first + second
assert asyncio.run(combined()) == 84
Background εργασία χρειάζεται υπευθυνότητα
Το create_task προγραμματίζει μια coroutine, αλλά πρέπει να κρατήσεις reference και να περιμένεις ή να εποπτεύεις το αποτέλεσμα μαζί με exceptions. Το να δημιουργήσεις task μόνο για να εξαφανιστεί warning μπορεί να χάσει εργασία στο shutdown. Το asyncio.TaskGroup περιμένει τα child tasks στο τέλος του group σε συμβατές εκδόσεις.
Έλεγχος: επιβεβαίωσε ότι η συνάρτηση επέστρεψε το σωστό αποτέλεσμα, όχι απλώς ότι εξαφανίστηκε warning. Πηγή: https://docs.python.org/3/library/asyncio-task.html
Coroutine object δεν σημαίνει εκτέλεση
Κάθε κλήση async def δημιουργεί coroutine, αλλά ο κώδικάς της δεν εκτελείται χωρίς await ή κατάλληλο scheduling. Σε μια async def main(), το await fetch() περιμένει το αποτέλεσμα. Το asyncio.create_task(fetch()) δημιουργεί task που προγραμματίζεται, όμως πρέπει να διαχειριστείς το completion, το cancellation και κάθε exception του. Μην χρησιμοποιείς create_task απλώς για να εξαφανιστεί το warning: ένα ξεχασμένο task μπορεί να αποτύχει χωρίς να ελεγχθεί. Φτιάξε μια επιτυχημένη και μια αποτυχημένη async λειτουργία, κάλεσέ τες μέσω asyncio.run(main()) και επιβεβαίωσε ότι καμία εξαίρεση δεν χάνεται.