You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This code should show a constantly increasing number, interspersed with groups of four characters read from
the usb_cdc.data serial terminal:
"""example that reads from the cdc data serial port in groups of four and printsto the console. The USB CDC data serial port will need enabling. This can be doneby copying examples/usb_cdc_boot.py to boot.py in the CIRCUITPY directoryMeanwhile a simple counter counts up every second and also printsto the console."""importasyncioimportusb_cdcasyncdefclient():
s=asyncio.StreamReader(usb_cdc.data)
whileTrue:
text=awaits.read(4)
print(text)
awaitasyncio.sleep(0)
asyncdefcounter():
i=0whileTrue:
print(i)
i+=1awaitasyncio.sleep(1)
asyncdefmain():
client_task=asyncio.create_task(client())
count_task=asyncio.create_task(counter())
awaitasyncio.gather(client_task, count_task)
asyncio.run(main())
What actually happens is 0 is printed, then nothing until four characters have been received on usb_cdc.data, and then this error message is produced:
Traceback (most recent call last):
File "code.py", line 39, in <module>
File "/lib/asyncio/core.py", line 292, in run
File "/lib/asyncio/core.py", line 256, in run_until_complete
File "/lib/asyncio/core.py", line 241, in run_until_complete
File "code.py", line 36, in main
File "/lib/asyncio/funcs.py", line 113, in gather
File "/lib/asyncio/funcs.py", line 108, in gather
File "/lib/asyncio/core.py", line 241, in run_until_complete
File "code.py", line 22, in client
File "/lib/asyncio/stream.py", line 63, in read
File "/lib/asyncio/core.py", line 152, in queue_read
File "/lib/asyncio/core.py", line 140, in _enqueue
AssertionError:
This is due to this code in asyncio.stream.Stream:
asyncdefread(self, n):
"""Read up to *n* bytes and return them. This is a coroutine. """core._io_queue.queue_read(self.s)
awaitcore.sleep(0)
returnself.s.read(n)
It seems that the call to core._io_queue.queue_read(self.s) sets up the asyncio main loop to poll for
updates to self.s (usb_cdc.data) in this instance, and the schedules the current task to be re-awoken when it happens.
It then calls await core.sleep(0) which almost immediately returns. self.s.read is then called which blocks everything until 4 characters are read.
Next time around, again core._io_queue.queue_read(self.s) is read, but this time there is already an entry waiting for usb_cdc.data to be updated and the code gets confused and raises an error.
This can be fixed by adding a yield statement instead of core.sleep(0) - I'll add a PR to that effect. However, I can see that the code previously did use that and I'm not sure why the change was made.
There is also an error in that if we add the yield, then the coroutine will pause until one character has been read (thus triggering the poll in core._io_queue), but it will then (again) block until the other 3 characters have been read. However, this time it will not crash. This probably needs to be fixed in python, probably using a scheme similar to Stream.read_exactly
The text was updated successfully, but these errors were encountered:
This code should show a constantly increasing number, interspersed with groups of four characters read from
the
usb_cdc.data
serial terminal:What actually happens is
0
is printed, then nothing until four characters have been received onusb_cdc.data
, and then this error message is produced:This is due to this code in
asyncio.stream.Stream
:It seems that the call to
core._io_queue.queue_read(self.s)
sets up the asyncio main loop to poll forupdates to
self.s
(usb_cdc.data
) in this instance, and the schedules the current task to be re-awoken when it happens.It then calls
await core.sleep(0)
which almost immediately returns.self.s.read
is then called which blocks everything until 4 characters are read.Next time around, again
core._io_queue.queue_read(self.s)
is read, but this time there is already an entry waiting forusb_cdc.data
to be updated and the code gets confused and raises an error.This can be fixed by adding a
yield
statement instead ofcore.sleep(0)
- I'll add a PR to that effect. However, I can see that the code previously did use that and I'm not sure why the change was made.There is also an error in that if we add the yield, then the coroutine will pause until one character has been read (thus triggering the poll in
core._io_queue
), but it will then (again) block until the other 3 characters have been read. However, this time it will not crash. This probably needs to be fixed in python, probably using a scheme similar toStream.read_exactly
The text was updated successfully, but these errors were encountered: