-
-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Open
Labels
py-coreRelates to py/ directory in sourceRelates to py/ directory in source
Description
I don't doubt that I'm doing something wrong here, but when I attempt to iterate over an async generator that contains an async for ...
loop, it crashes with:
assertion "heap->next == NULL" failed: file "../../py/pairheap.h", line 94, function: mp_pairheap_pop
Script
try:
import uasyncio as asyncio
except ImportError:
import asyncio
# Adapted from micropython-async AsyncIterable example:
# https://github.com/peterhinch/micropython-async/blob/master/v3/docs/TUTORIAL.md#42-asynchronous-iterators
class AsyncGenerator:
def __init__(self, gen):
self.gen = gen
def __aiter__(self):
return self
async def __anext__(self):
v = await self.next()
if v is StopIteration:
raise StopAsyncIteration
return v
async def next(self):
await asyncio.sleep(0)
try:
if hasattr(self.gen, '__anext__'):
return await self.gen.__anext__()
return next(self.gen)
except StopIteration:
return StopIteration
# AsyncGenerator decorator.
def async_generator(func):
def wrapper(*args, **kwargs):
return AsyncGenerator(func(*args, **kwargs))
return wrapper
# A normal Python async generator function with inner SYNC loop,
# wrapped with AsyncGenerator.
@async_generator
async def agen1():
for i in range(10):
yield i
# A normal Python async generator function with inner ASYNC loop,
# wrapped with AsyncGenerator.
@async_generator
async def agen2(agen):
async for i in agen:
yield i
# Consume an async generator and print each value.
async def consume(gen):
async for i in gen:
print(i)
def go():
run = asyncio.get_event_loop().run_until_complete
print('# Ok')
run(consume(agen1()))
print('# Not Ok')
run(consume(agen2(agen1())))
Micropython v1.13 ESP32 Output:
>>> go()
# Ok
0
1
2
3
4
5
6
7
8
9
# Not Ok
None
assertion "heap->next == NULL" failed: file "../../py/pairheap.h", line 94, function: mp_pairheap_pop
abort() was called at PC 0x4016a1eb on core 1
ELF file SHA256: 0000000000000000000000000000000000000000000000000000000000000000
Backtrace: 0x4008fcb3:0x3ffce300 0x4008ffd1:0x3ffce320 0x4016a1eb:0x3ffce340 0x400edf8b:0x3ffce370 0x400e3781:0x3ffce390 0x400df7a1:0x3ffce3b0 0x400df8c9:0x3ffce3d0 0x400ed011:0x3ffce3f0 0x400e390c:0x3ffce490 0x400df7a1:0x3ffce4c0 0x400ecf89:0x3ffce4e0 0x400e390c:0x3ffce580 0x400df7a1:0x3ffce5f0 0x400ecf89:0x3ffce610 0x400e390c:0x3ffce6b0 0x400df7a1:0x3ffce720 0x400ecf89:0x3ffce740 0x400e390c:0x3ffce7e0 0x400df7a1:0x3ffce840 0x400df7ca:0x3ffce860 0x40104967:0x3ffce880 0x40104b71:0x3ffce910 0x400f5d3c:0x3ffce950 0x400992f6:0x3ffce980
Rebooting...
Python 3.6 Output
>>> go()
# Ok
0
1
2
3
4
5
6
7
8
9
# Not Ok
0
1
2
3
4
5
6
7
8
9
Metadata
Metadata
Assignees
Labels
py-coreRelates to py/ directory in sourceRelates to py/ directory in source