33Asynchronous in REPL: Autoawait
44===============================
55
6+ .. note ::
7+
8+ This feature is experimental and behavior can change betwen python and
9+ IPython version without prior deprecation.
10+
611Starting with IPython 7.0, and when user Python 3.6 and above, IPython offer the
712ability to run asynchronous code from the REPL. Constructs which are
813:exc: `SyntaxError ` s in the Python REPL can be used seamlessly in IPython.
@@ -12,10 +17,10 @@ notebook interface or any other frontend using the Jupyter protocol will need to
1217use a newer version of IPykernel. The details of how async code runs in
1318IPykernel will differ between IPython, IPykernel and their versions.
1419
15- When a supported library is used, IPython will automatically ` await ` Futures and
16- Coroutines in the REPL. This will happen if an :ref: `await < await >` (or any
17- other async constructs like async-with, async-for) is use at top level scope, or
18- if any structure valid only in `async def
20+ When a supported library is used, IPython will automatically allow Futures and
21+ Coroutines in the REPL to be `` await `` ed . This will happen if an :ref: `await
22+ <await>` (or any other async constructs like async-with, async-for) is use at
23+ top level scope, or if any structure valid only in `async def
1924<https://docs.python.org/3/reference/compound_stmts.html#async-def> `_ function
2025context are present. For example, the following being a syntax error in the
2126Python REPL::
@@ -58,15 +63,13 @@ use the :magic:`%autoawait` magic to toggle the behavior at runtime::
5863 In [1]: %autoawait False
5964
6065 In [2]: %autoawait
61- IPython autoawait is `Off`, and set to use `IPython.core.interactiveshell._asyncio_runner `
66+ IPython autoawait is `Off`, and set to use `asyncio `
6267
6368
6469
6570By default IPython will assume integration with Python's provided
6671:mod: `asyncio `, but integration with other libraries is provided. In particular
67- we provide experimental integration with the ``curio `` and ``trio `` library, the
68- later one being necessary if you require the ability to do nested call of
69- IPython's ``embed() `` functionality.
72+ we provide experimental integration with the ``curio `` and ``trio `` library.
7073
7174You can switch current integration by using the
7275``c.InteractiveShell.loop_runner `` option or the ``autoawait <name
@@ -111,7 +114,7 @@ other features of IPython and various registered extensions. In particular if yo
111114are a direct or indirect user of the AST transformers, these may not apply to
112115your code.
113116
114- When Using command line IPython, the default loop (or runner) does not process
117+ When using command line IPython, the default loop (or runner) does not process
115118in the background, so top level asynchronous code must finish for the REPL to
116119allow you to enter more code. As with usual Python semantic, the awaitables are
117120started only when awaited for the first time. That is to say, in first example,
@@ -122,25 +125,20 @@ Effects on IPython.embed()
122125==========================
123126
124127IPython core being asynchronous, the use of ``IPython.embed() `` will now require
125- a loop to run. In order to allow ``IPython.embed() `` to be nested, as most event
126- loops can't be nested, ``IPython.embed() `` default to a pseudo-synchronous mode,
127- where async code is not allowed. This mode is available in classical IPython
128- using ``%autoawait sync ``
129-
130-
131-
132- This affect the ability to nest ``IPython.embed() `` which may
133- require you to install alternate IO libraries like ``curio `` and ``trio ``
134-
128+ a loop to run. By default IPython will use a fake coroutine runner which should
129+ allow ``IPython.embed() `` to be nested. Though this will prevent usage of the
130+ ``autoawait `` feature when using IPython embed.
135131
132+ You can set explicitly a coroutine runner for ``embed() `` if you desire to run
133+ asynchronous code, the exact behavior is though undefined.
136134
137135Internals
138136=========
139137
140138As running asynchronous code is not supported in interactive REPL (as of Python
141- 3.7) we have to rely to a number of complex workaround to allow this to happen.
142- It is interesting to understand how this works in order to comprehend potential
143- bugs, or provide a custom runner.
139+ 3.7) we have to rely to a number of complex workaround and heuristic to allow
140+ this to happen. It is interesting to understand how this works in order to
141+ comprehend potential bugs, or provide a custom runner.
144142
145143Among the many approaches that are at our disposition, we find only one that
146144suited out need. Under the hood we use the code object from a async-def function
@@ -168,8 +166,10 @@ On top of the above there are significant modification to the AST of
168166significant overhead to this kind of code.
169167
170168By default the generated coroutine function will be consumed by Asyncio's
171- ``loop_runner = asyncio.get_evenloop().run_until_complete() `` method. It is
172- though possible to provide your own.
169+ ``loop_runner = asyncio.get_evenloop().run_until_complete() `` method if
170+ ``async `` mode is deemed necessary, otherwise the coroutine will just be
171+ exhausted in a simple runner. It is though possible to change the default
172+ runner.
173173
174174A loop runner is a *synchronous * function responsible from running a coroutine
175175object.
@@ -208,3 +208,6 @@ We can set it up by passing it to ``%autoawait``::
208208Asynchronous programming in python (and in particular in the REPL) is still a
209209relatively young subject. We expect some code to not behave as you expect, so
210210feel free to contribute improvements to this codebase and give us feedback.
211+
212+ We invite you to thoroughly test this feature and report any unexpected behavior
213+ as well as propose any improvement.
0 commit comments