Skip to content

Commit 71ebf31

Browse files
committed
Tutorial: add warning on get_event_loop() args.
1 parent b08ab3c commit 71ebf31

File tree

1 file changed

+38
-7
lines changed

1 file changed

+38
-7
lines changed

TUTORIAL.md

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ asyncio and includes a section for complete beginners.
5252
6.4 [Testing](./TUTORIAL.md#64-testing)
5353
6.5 [A common error](./TUTORIAL.md#65-a-common-error) This can be hard to find.
5454
6.6 [Socket programming](./TUTORIAL.md#66-socket-programming)
55+
6.7 [Event loop constructor args](./TUTORIAL.md#67-event-loop-constructor-args)
5556
7. [Notes for beginners](./TUTORIAL.md#7-notes-for-beginners)
5657
7.1 [Problem 1: event loops](./TUTORIAL.md#71-problem-1:-event-loops)
5758
7.2 [Problem 2: blocking methods](./TUTORIAL.md#7-problem-2:-blocking-methods)
@@ -240,7 +241,8 @@ The event loop instance is a singleton, instantiated by a program's first call
240241
to `asyncio.get_event_loop()`. This takes two optional integer args being the
241242
lengths of the two coro queues. Typically both will have the same value being
242243
at least the number of concurrent coros in the application. The default of 16
243-
is usually sufficient.
244+
is usually sufficient. If using non-default values see
245+
[Event loop constructor args](./TUTORIAL.md#67-event-loop-constructor-args).
244246

245247
If a coro needs to call an event loop method (usually `create_task`), calling
246248
`asyncio.get_event_loop()` (without args) will efficiently return it.
@@ -984,9 +986,9 @@ while a coroutine awaiting the outcome polls the object each time it is
984986
scheduled.
985987

986988
Polling may be effected in two ways, explicitly or implicitly. The latter is
987-
performed by using the `stream I/O` mechanism which is a system designed for stream
988-
devices such as UARTs and sockets. At its simplest explicit polling may consist
989-
of code like this:
989+
performed by using the `stream I/O` mechanism which is a system designed for
990+
stream devices such as UARTs and sockets. At its simplest explicit polling may
991+
consist of code like this:
990992

991993
```python
992994
async def poll_my_device():
@@ -1359,11 +1361,11 @@ time of writing there is a bug in `uasyncio` which prevents this from woking.
13591361
See [this GitHub thread](https://github.com/micropython/micropython/pull/3836#issuecomment-397317408).
13601362
There are two solutions. A workround is to write two separate drivers, one
13611363
read-only and the other write-only. Alternatively the
1362-
[fast_io](./FASTPOLL.md) addresses this.
1364+
[fast_io](./FASTPOLL.md) version addresses this.
13631365

13641366
In the official `uasyncio` I/O is scheduled quite infrequently. See
13651367
[see this GitHub RFC](https://github.com/micropython/micropython/issues/2664).
1366-
The `fast_io` version addresses this issue.
1368+
The [fast_io](./FASTPOLL.md) version addresses this issue.
13671369

13681370
###### [Contents](./TUTORIAL.md#contents)
13691371

@@ -1374,7 +1376,7 @@ The demo provides a complete device driver example: a receiver/decoder for an
13741376
infra red remote controller. The following notes are salient points regarding
13751377
its `asyncio` usage.
13761378

1377-
A pin interrupt records the time of a state change (in us) and sets an event,
1379+
A pin interrupt records the time of a state change (in μs) and sets an event,
13781380
passing the time when the first state change occurred. A coro waits on the
13791381
event, yields for the duration of a data burst, then decodes the stored data
13801382
before calling a user-specified callback.
@@ -1552,6 +1554,35 @@ An alternative approach is to use blocking sockets with `StreamReader` and
15521554

15531555
###### [Contents](./TUTORIAL.md#contents)
15541556

1557+
## 6.7 Event loop constructor args
1558+
1559+
A subtle bug can arise if you need to instantiate the event loop with non
1560+
default values. Instantiation should be performed before running any other
1561+
`asyncio` code. This is because the code may acquire the event loop. In
1562+
doing so it initialises it to the default values:
1563+
1564+
```python
1565+
import uasyncio as asyncio
1566+
import some_module
1567+
bar = some_module.Bar() # Constructor calls get_event_loop()
1568+
# and renders these args inoperative
1569+
loop = asyncio.get_event_loop(runq_len=40, waitq_len=40)
1570+
```
1571+
1572+
Given that importing a module can run code the only safe way is to instantiate
1573+
the event loop immediately after importing `uasyncio`.
1574+
1575+
```python
1576+
import uasyncio as asyncio
1577+
loop = asyncio.get_event_loop(runq_len=40, waitq_len=40)
1578+
import some_module
1579+
bar = some_module.Bar() # The get_event_loop() call is now safe
1580+
```
1581+
1582+
Ref [this issue](https://github.com/micropython/micropython-lib/issues/295).
1583+
1584+
###### [Contents](./TUTORIAL.md#contents)
1585+
15551586
# 7 Notes for beginners
15561587

15571588
These notes are intended for those new to asynchronous code. They start by

0 commit comments

Comments
 (0)