Debugger silently calls __iter__() and next()
See original GitHub issueTry to debug this code:
import os
class MyIterator(list):
def __iter__(self): return self
def next(self): os._exit(1)
a = MyIterator()
print(a) # put a breakpoint here
You will find that the debugger will quit before you even attempt to do anything.
This should not happen. If the debugger insists on iterating through members of every subclass of list
silently, then it should really call list.__iter__(instance)
rather than iter(instance)
. Otherwise it breaks debugging on the entire codebase, since the iterator is silently consumed and hence the program no longer behaves correctly when stepping through.
Note that similar problems probably exist for other types, not just list
. More generally, I think the debugging experience of subclasses of basic types needs improvement; it is currently not robust.
(This bug probably touches on similar aspects of the debugger as #3505.)
Issue Analytics
- State:
- Created 6 years ago
- Comments:26 (14 by maintainers)
Top Results From Across the Web
Access iterator object within a debugger - python
The only thing you can do with an iterator is call next() on it to get the next element (or an Exception if...
Read more >Deprecate "old-style iteration protocol"? - Python discussion
The problem here is that your “identity dict” behaves as an infinite lazy sequence. There is nothing wrong with infinite lazy sequences, but...
Read more >How to Make the Most of Your Python Debugger in VSCode
Step Over button will take the debugger from the current line to the next line in the code (in our case, the print...
Read more >Consider using iterator transforms instead of explicit loops
The core Iterator trait has a very simple interface: a single method next that yields Some items until it doesn't ( None )....
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
As we discussed on the other bug, “improving” debugging of subclasses really just means disabling it. We need to balance that against user expectations, which is that objects implementing a certain protocol will adhere to that protocol - by convention, iteration should not terminate the process, and in particular iteration of an iterable should not have observable side effects. Our debugger breaking here is a good indication that anyone using that code will likely also be broken.
Basically, we don’t want to cripple most users’ experiences just in case someone broke the rules and expects their broken code to still work correctly.
The check for
iter(self) is self
follows the iterator protocol - per PEP 234:I agree that it’s a hack - it’s not really meant to detect iterators - but it’s the best one that we can come up with, since there’s no standard way to do so with Python (although it would be nice to have a way to ask any object if iterating it is one-off or not, and whether it’s expensive or not).
That said, looking at the code more closely, I’m not sure if this is actually the code path that leads to your problem. It appears that when we’re reporting children (this is after retrieving them in
enum_child_locally
), we’re actually callinglen()
on each of those values:where
get_object_len
is:and ditto in
report_execution_result
. And when used on an iterator,len
will iterate it. The same logic should be extended there.