diff --git a/drafts/2018-03-09-python-asyncio.org b/drafts/2018-03-09-python-asyncio.org index 6bbbf0d..c59a2a2 100644 --- a/drafts/2018-03-09-python-asyncio.org +++ b/drafts/2018-03-09-python-asyncio.org @@ -25,14 +25,16 @@ over to some other code, whereas calling "whenever" means retaining control but queuing up some code to be run in the background asychronously (as much as possible). -| Call from | Call to | When | How | -|-----------+-----------+----------+-----------------------------| -| Either | Function | Now | Normal function call | -| Function | Coroutine | Now | `.run_*` in event loop | -| Coroutine | Coroutine | Now | `await` | -| Either | Function | Whenever | Event loop `.call_*()` | -| Either | Coroutine | Whenever | Event loop `.create_task()` | -| | | | `asyncio.ensure_future()` | +| Call from | Call to | When/where | How | +|-----------+-----------+-----------------------+-----------------------------------------------| +| Either | Function | Now, same thread | Normal function call | +| Function | Coroutine | Now, same thread | ~.run_*~ in event loop | +| Coroutine | Coroutine | Now, same thread | ~await~ | +| Either | Function | Whenever, same thread | Event loop ~.call_*()~ | +| Either | Coroutine | Whenever, same thread | Event loop ~.create_task()~ | +| | | | ~asyncio.ensure_future()~ | +| Either | Function | Now, another thread | ~.run_in_executor()~ on ~ThreadPoolExecutor~ | +| Either | Function | Now, another process | ~.run_in_executor()~ on ~ProcessPoolExecutor~ | * Futures & Coroutines @@ -44,15 +46,15 @@ coroutines and futures. My summary on what I figured out is below. It just happens that both allow you to call things asychronously. However, you can use coroutines/asyncio without ever touching a Future. Likewise, you can use a Future without ever touching a -coroutine or asyncio. Note that its `.result()` call isn't a +coroutine or asyncio. Note that its ~.result()~ call isn't a coroutine. ** They can still encapsulate each other. -A coroutine can encapsulate a Future simply by `await`ing it. +A coroutine can encapsulate a Future simply by using ~await~ on it. -A Future can encapsulate a coroutine with [[https://docs.python.org/3/library/asyncio-task.html#asyncio.ensure_future][asyncio.ensure_future()]] or -the event loop's [[https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.create_task][.create_task()]]. +A Future can encapsulate a coroutine with [[https://docs.python.org/3/library/asyncio-task.html#asyncio.ensure_future][asyncio.ensure\_future()]] or +the event loop's [[https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.create_task][.create\_task()]]. ** Futures can implement asychronicity(?) differently @@ -79,13 +81,14 @@ which is available only when a coroutine has been scheduled to run. on a project. I ran into many issues with this combination. Qt's juggling of multiple event loops seemed to cause many problems here, and I still have some unsolved issues in which calls -`run_until_complete` cause coroutines to die early with an exception +~run_until_complete~ cause coroutines to die early with an exception because the event loop appears to have died. This came up regularly for me because of how often I would want a Qt slot to queue a task in the background, and it seems this is an acknowledge [[https://github.com/harvimt/quamash/issues/33][issue]]. -There is also [[https://github.com/MagicStack/uvloop\][uvloop]]. I have no need for extra performance (nor could -I really use it alongside Qt), but it's helpful to know about. +There is also [[https://github.com/MagicStack/uvloop\][uvloop]]. I presently have no need for extra performance +(nor could I really use it alongside Qt), but it's helpful to know +about. # Also: What about coroutine generators? # Are they anything special?