[issue44622] async-for loops are traced incorrectly in Python 3.10
Ned Batchelder
report at bugs.python.org
Tue Jul 13 09:03:51 EDT 2021
New submission from Ned Batchelder <ned at nedbatchelder.com>:
In Python 3.10, the traces at the end of an async-for loop are incorrect and different than at the end of a for-loop.
------------------------------
import linecache, sys
def trace(frame, event, arg):
# The weird globals here is to avoid a NameError on shutdown...
if frame.f_code.co_filename == globals().get("__file__"):
lineno = frame.f_lineno
print("{} {}: {}".format(event[:4], lineno, linecache.getline(__file__, lineno).rstrip()))
return trace
import asyncio
class AsyncIter:
def __init__(self, items): self.items = items
async def __aiter__(self):
for i in self.items: yield i
async def test1():
async for i in AsyncIter([1]):
print(f"test1 {i}")
def test2():
for i in [1]:
print(f"test2 {i}")
print(sys.version)
sys.settrace(trace)
asyncio.run(test1())
test2()
------------------------------------
In 3.7, 3.8 and 3.9, the two for loops behave the same: the loop jumps back to the "for" statement, and then returns (the arrowed lines):
3.9.5 (default, May 5 2021, 06:50:43)
[Clang 12.0.0 (clang-1200.0.32.29)]
call 18: async def test1():
line 19: async for i in AsyncIter([1]):
call 13: def __init__(self, items): self.items = items
line 13: def __init__(self, items): self.items = items
retu 13: def __init__(self, items): self.items = items
call 15: async def __aiter__(self):
line 16: for i in self.items: yield i
retu 16: for i in self.items: yield i
exce 19: async for i in AsyncIter([1]):
line 20: print(f"test1 {i}")
test1 1
line 19: async for i in AsyncIter([1]):
call 16: for i in self.items: yield i
line 16: for i in self.items: yield i
retu 16: for i in self.items: yield i
exce 19: async for i in AsyncIter([1]):
> retu 19: async for i in AsyncIter([1]):
call 22: def test2():
line 23: for i in [1]:
line 24: print(f"test2 {i}")
test2 1
line 23: for i in [1]:
> retu 23: for i in [1]:
In 3.10, the for loop behaves the same, but now the async-for traces the body once more when it doesn't execute, and returns from the body of the loop (the starred line):
3.10.0b4 (default, Jul 11 2021, 13:51:53) [Clang 12.0.0 (clang-1200.0.32.29)]
call 18: async def test1():
line 19: async for i in AsyncIter([1]):
call 13: def __init__(self, items): self.items = items
line 13: def __init__(self, items): self.items = items
retu 13: def __init__(self, items): self.items = items
call 15: async def __aiter__(self):
line 16: for i in self.items: yield i
retu 16: for i in self.items: yield i
exce 19: async for i in AsyncIter([1]):
line 20: print(f"test1 {i}")
test1 1
line 19: async for i in AsyncIter([1]):
call 16: for i in self.items: yield i
line 16: for i in self.items: yield i
retu 16: for i in self.items: yield i
exce 19: async for i in AsyncIter([1]):
* line 20: print(f"test1 {i}")
retu 20: print(f"test1 {i}")
call 22: def test2():
line 23: for i in [1]:
line 24: print(f"test2 {i}")
test2 1
line 23: for i in [1]:
> retu 23: for i in [1]:
----------
components: Interpreter Core
keywords: 3.10regression
messages: 397396
nosy: Mark.Shannon, nedbat
priority: normal
severity: normal
status: open
title: async-for loops are traced incorrectly in Python 3.10
type: behavior
versions: Python 3.10
_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue44622>
_______________________________________
More information about the Python-bugs-list
mailing list