J'ai du code asyncio qui fonctionne très bien dans l'interpréteur Python (CPython 3.6.2). Je voudrais maintenant l'exécuter dans un bloc-notes Jupyter avec un noyau IPython.
Je peux l'exécuter avec
import asyncio
asyncio.get_event_loop().run_forever()
et bien que cela semble fonctionner, il semble également bloquer le bloc-notes et ne semble pas jouer à Nice avec le bloc-notes.
Ma compréhension est que Jupyter utilise Tornado sous le capot, j'ai donc essayé de installer une boucle d'événement Tornado comme recommandé dans les documents Tornado :
from tornado.platform.asyncio import AsyncIOMainLoop
AsyncIOMainLoop().install()
Cependant, cela donne l'erreur suivante:
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
<ipython-input-1-1139449343fc> in <module>()
1 from tornado.platform.asyncio import AsyncIOMainLoop
----> 2 AsyncIOMainLoop().install()
~\AppData\Local\Continuum\Anaconda3\envs\numismatic\lib\site- packages\tornado\ioloop.py in install(self)
179 `IOLoop` (e.g., :class:`tornado.httpclient.AsyncHTTPClient`).
180 """
--> 181 assert not IOLoop.initialized()
182 IOLoop._instance = self
183
AssertionError:
Enfin, j'ai trouvé la page suivante: http://ipywidgets.readthedocs.io/en/stable/examples/Widget%20Asynchronous.html
j'ai donc ajouté une cellule avec le code suivant:
import asyncio
from ipykernel.eventloops import register_integration
@register_integration('asyncio')
def loop_asyncio(kernel):
'''Start a kernel with asyncio event loop support.'''
loop = asyncio.get_event_loop()
def kernel_handler():
loop.call_soon(kernel.do_one_iteration)
loop.call_later(kernel._poll_interval, kernel_handler)
loop.call_soon(kernel_handler)
try:
if not loop.is_running():
loop.run_forever()
finally:
loop.run_until_complete(loop.shutdown_asyncgens())
loop.close()
et dans la cellule suivante j'ai couru:
%gui asyncio
Cela a fonctionné mais je ne comprends pas vraiment pourquoi et comment cela fonctionne. Quelqu'un peut-il m'expliquer cela?
EDIT 21 FÉVRIER 2019: Problème résolu
Ce n'est plus un problème sur la dernière version de Jupyter Notebook. Les auteurs de Jupyter Notebook ont détaillé le cas ici .
La réponse ci-dessous était la réponse originale qui a été marquée comme correcte par l'op.
Cela a été publié il y a un peu, mais au cas où d'autres personnes chercheraient une explication et une solution au problème de l'exécution de code asynchrone dans Jupyter Notebook;
La mise à jour Tornado 5.0 de Jupyter a briqué les fonctionnalités asyncio après l'ajout de sa propre boucle d'événement asyncio:
Ainsi, pour que toute fonctionnalité asyncio s'exécute sur Jupyter Notebook, vous ne pouvez pas invoquer une run_until_complete()
, car la boucle que vous recevrez de asyncio.get_event_loop()
sera active.
Au lieu de cela, vous devez ajouter une tâche à la boucle actuelle:
import asyncio
loop = asyncio.get_event_loop()
loop.create_task(some_async_function())
Un exemple simple fonctionnant sur Jupyter Notebook:
Ce n'est plus un problème dans la dernière version de jupyter!
https://blog.jupyter.org/ipython-7-0-async-repl-a35ce050f7f7
Il suffit d'écrire une fonction asynchrone, puis de l'attendre directement dans une cellule jupyter.
async def fn():
print('hello')
await asyncio.sleep(1)
print('world')
await fn()
Mon moment aha avec Asyncio dans Jupyter ressemble à ceci:
import time,asyncio
async def count():
print("count one")
await asyncio.sleep(1)
print("count four")
async def count_further():
print("count two")
await asyncio.sleep(1)
print("count five")
async def count_even_further():
print("count three")
await asyncio.sleep(1)
print("count six")
async def main():
await asyncio.gather(count(), count_further(), count_even_further())
s = time.perf_counter()
await main()
elapsed = time.perf_counter() - s
print(f"Script executed in {elapsed:0.2f} seconds.")
Production:
count one
count two
count three
count four
count five
count six
Script executed in 1.00 seconds.
À l'origine d'ici, mais l'exemple n'était pas clair pour moi au début: https://realpython.com/async-io-python/
J'ai récemment rencontré le problème de ne pas pouvoir exécuter du code asyncio dans un ordinateur portable Jupyter. Le problème est abordé ici: https://github.com/jupyter/notebook/issues/3397
J'ai essayé l'une des solutions dans la discussion et cela a résolu le problème jusqu'à présent.
pip3 install tornado==4.5.3
Cela a remplacé la version 5.x de tornado installée par défaut.
Le code asyncio dans un bloc-notes Jupyter s'est ensuite exécuté comme prévu.