Comment créer un emballage qui donne aux tâches de céleri l'apparence suivante: asyncio.Task
? Ou existe-t-il un meilleur moyen d’intégrer le céleri avec asyncio
?
@asksol, créateur du céleri, a dit ceci: :
Il est assez courant d’utiliser Celery en tant que couche distribuée au-dessus d’infrastructures d’E/S asynchrones (astuce: acheminer des tâches liées à la CPU à un préposé à l’emploi du forfork signifie qu’elles ne bloqueront pas votre boucle d’événements.
Mais je n'ai trouvé aucun exemple de code spécifique au framework asyncio
.
Cela sera possible à partir de la version 5.0 de Celery comme indiqué sur le site officiel:
http://docs.celeryproject.org/en/4.0/whatsnew-4.0.html#preface
- La prochaine version majeure de Celery ne supportera que Python 3.5, si nous prévoyons de tirer parti de la nouvelle bibliothèque asyncio.
- En abandonnant la prise en charge de Python 2, nous pourrons supprimer d’énormes quantités de code de compatibilité, et utiliser Python 3.5 nous permet de tirer parti des concepts de frappe, async/wait, asyncio et de concepts similaires.
_ {Ce qui précède a été cité à partir du lien précédent. _
La meilleure chose à faire est donc d’attendre que la version version 5.0 soit distribuée!
En attendant, bon codage :)
Vous pouvez intégrer tout appel bloquant dans une tâche en utilisant run_in_executor
comme décrit dans documentation , j'ai également ajouté dans l'exemple un timeout personnalisé :
def run_async_task(
target,
*args,
timeout = 60,
**keywords
) -> Future:
loop = asyncio.get_event_loop()
return asyncio.wait_for(
loop.run_in_executor(
executor,
functools.partial(target, *args, **keywords)
),
timeout=timeout,
loop=loop
)
loop = asyncio.get_event_loop()
async_result = loop.run_until_complete(
run_async_task, your_task.delay, some_arg, some_karg=""
)
result = loop.run_until_complete(
run_async_task, async_result.result
)
La méthode la plus propre que j'ai trouvée consiste à envelopper la fonction async
dans asgiref.sync.async_to_sync
(from asgiref
):
from asgiref.sync import async_to_sync
from celery.task import periodic_task
async def return_hello():
await sleep(1)
return 'hello'
@periodic_task(
run_every=2,
name='return_hello',
)
def task_return_hello():
async_to_sync(return_hello)()
J'ai tiré cet exemple d'un blog post j'ai écrit.