This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: checking for membership in itertools.count enters infinite loop with no way to exit
Type: behavior Stage: resolved
Components: Library (Lib) Versions: Python 3.8
process
Status: closed Resolution: duplicate
Dependencies: Superseder: Make itertools iterators interruptible
View: 31815
Assigned To: Nosy List: Dan Rose, Jeffrey.Kintscher, martin.panter, rhettinger, serhiy.storchaka, terry.reedy
Priority: normal Keywords:

Created on 2019-05-25 04:22 by Dan Rose, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Messages (8)
msg343452 - (view) Author: Dan Rose (Dan Rose) * Date: 2019-05-25 04:22
Checking membership in `itertools.count()` will either return True in linear time or enter an infinite loop that cannot be terminated with Ctrl-c. This

```
import itertools
1 in itertools.count(0,2)
```

It is expected that the above code will use an efficient (O(1)) membership algorithm like range objects.
msg343455 - (view) Author: SilentGhost (SilentGhost) * (Python triager) Date: 2019-05-25 06:33
This seem like a misdirected expectation. count returns a regular iterator and the purpose behind it is not to enable membership checks, this only works because it's a regular iterators and normal rules for checking membership are applied.

In any case, it is possible to write an infinite loop in Python either by accident or intentionally, this doesn't seem like a reasonable rationale for making this sort changes.
msg343458 - (view) Author: Martin Panter (martin.panter) * (Python committer) Date: 2019-05-25 08:07
Problems with long-running iterators are already discussed in:

Issue 31815: rejected proposal to check for interrupts
Issue 33939: proposal to flag iterators as being infinite
msg343486 - (view) Author: Dan Rose (Dan Rose) * Date: 2019-05-25 15:20
Reopening. While my behavioral expectation may be wrong, the current behavior is inappropriate. It would make more sense for count to have a `__contains__` method which raises a TypeError.
msg343491 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2019-05-25 16:48
Adding the __contains__() method to the count iterator would not solve the general problem with infinite iterators. For example with the following expressions:

    -1 in filter(None, itertools.count())
    -1 in map(float, itertools.count())

It is not worth to add a method just to handle a single case of misusing. You should not use "in" with infinite iterators.
msg343496 - (view) Author: Dan Rose (Dan Rose) * Date: 2019-05-25 17:30
The general problem with infinite iterators is indeed a bigger issue and its resolution would probably resolve this issue too. With the examples you gave at least the user can ctrl-c to interrupt. Entering an infinite, *uninterruptible* loop is a consequence so bad that it deserves a guard rail.

> On May 25, 2019, at 11:48, Serhiy Storchaka <report@bugs.python.org> wrote:
> 
> 
> Serhiy Storchaka <storchaka+cpython@gmail.com> added the comment:
> 
> Adding the __contains__() method to the count iterator would not solve the general problem with infinite iterators. For example with the following expressions:
> 
>    -1 in filter(None, itertools.count())
>    -1 in map(float, itertools.count())
> 
> It is not worth to add a method just to handle a single case of misusing. You should not use "in" with infinite iterators.
> 
> ----------
> nosy: +serhiy.storchaka
> 
> _______________________________________
> Python tracker <report@bugs.python.org>
> <https://bugs.python.org/issue37040>
> _______________________________________
msg343497 - (view) Author: Dan Rose (Dan Rose) * Date: 2019-05-25 17:33
Oops you are right. These enter uninterruptible loops too. They are exceptional situations and should do the expected thing - throw exceptions as well.
msg344120 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2019-05-31 20:30
Dan, please leave this closed.  It duplicates #31815 and should be closed on that grounds alone, regardless of the status of the latter.  #31815 was closed in favor of #33939, which is open, with ongoing discussion.  Resolution either way is blocked because different core developers disagree.
History
Date User Action Args
2022-04-11 14:59:15adminsetgithub: 81221
2019-05-31 20:30:23terry.reedysetstatus: open -> closed

nosy: + terry.reedy
messages: + msg344120
resolution: duplicate

superseder: Make itertools iterators interruptible
2019-05-28 05:42:50Jeffrey.Kintschersetnosy: + Jeffrey.Kintscher
2019-05-25 17:33:22Dan Rosesetmessages: + msg343497
2019-05-25 17:30:58Dan Rosesetmessages: + msg343496
2019-05-25 16:48:02serhiy.storchakasetnosy: + serhiy.storchaka
messages: + msg343491
2019-05-25 15:35:10SilentGhostsetnosy: - SilentGhost
2019-05-25 15:20:23Dan Rosesetstatus: closed -> open
resolution: rejected -> (no value)
messages: + msg343486
2019-05-25 08:07:37martin.pantersetnosy: + martin.panter
messages: + msg343458
2019-05-25 06:33:08SilentGhostsetstatus: open -> closed

type: behavior
versions: + Python 3.8, - Python 3.7
nosy: + SilentGhost, rhettinger

messages: + msg343455
resolution: rejected
stage: resolved
2019-05-25 04:22:05Dan Rosecreate