The Wayback Machine - https://web.archive.org/web/20221209100652/https://github.com/python/cpython/issues/100111
Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

StopIteration Exception is ignored in map() #100111

Open
shner-elmo opened this issue Dec 8, 2022 · 1 comment
Open

StopIteration Exception is ignored in map() #100111

shner-elmo opened this issue Dec 8, 2022 · 1 comment
Labels
pending The issue will be closed if no feedback is provided type-bug An unexpected behavior, bug, or error

Comments

@shner-elmo
Copy link

shner-elmo commented Dec 8, 2022

Bug report

def func(x):
    raise StopIteration

>>> list(map(func, [1, 2, 3]))
[]

As you can see map() ignores the Exception and instead stops iterating on the first loop.
It seems like it simply mistakes the Exception raised from the function with the one from the Iterator, so it thinks its supposed to stop iterating, and therefore it quits early.

In fact if we overwrite the map() function like so, it will raise it properly:

def map(func, it):
    it = iter(it)
    while True:
        try:
            n = next(it)
        except StopIteration:
            return
        yield func(n)

>>> list(map(func, [1, 2, 3]))
...
RuntimeError: generator raised StopIteration

But when call the function directly on the next() element then the same thing happens

def map(func, it):
    it = iter(it)
    while True:
        try:
            yield func(next(it))
        except StopIteration:
            return

>>> list(map(func, [1, 2, 3]))
[]

For those wondering how I came across this bug, it happened when I was calling next() on a bunch of iterators,
which as you can see, made an infinite loop since map() would confuse the Exception raised from next() of the function that was passed with next() when iterating through the iterable that was passed to map()

iterables = [[1, 3, 109, 3], (x for x in range(23)), {'a', '2', 'c', 's'}, (1, 2, 3)]
iterators = [iter(x) for x in iterables]
while True:
    print(tuple(map(next, iterators)))
(1, 0, 's', 1)
(3, 1, '2', 2)
(109, 2, 'c', 3)
(3, 3, 'a')
()
()
()
()
# and it goes on infinetly...

Your environment

  • CPython versions tested on: 3.10.7
  • Operating system and architecture: Windows-10, AMD64, 64bit
@shner-elmo shner-elmo added the type-bug An unexpected behavior, bug, or error label Dec 8, 2022
@sweeneyde
Copy link
Member

sweeneyde commented Dec 8, 2022

This seems mostly like a duplicate of #90779

@sobolevn sobolevn added the pending The issue will be closed if no feedback is provided label Dec 8, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pending The issue will be closed if no feedback is provided type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

3 participants