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

Could tqdm read my iterator __len__() after __iter__() is called and not before ? #853

Open
5 of 8 tasks
redorff opened this issue Nov 27, 2019 · 1 comment
Open
5 of 8 tasks
Assignees
Labels
question/docs ‽ Documentation clarification candidate

Comments

@redorff
Copy link

redorff commented Nov 27, 2019

  • I have marked all applicable categories:
    • exception-raising bug
    • visual output bug
    • documentation request (i.e. "X is missing from the documentation." If instead I want to ask "how to use X?" I understand StackOverflow#tqdm is more appropriate)
    • new feature request
  • I have visited the source website, and in particular
    read the known issues
  • I have searched through the issue tracker for duplicates
  • I have mentioned version numbers, operating system and
    environment, where applicable:
    import tqdm, sys
    print(tqdm.__version__, sys.version, sys.platform)

4.36.1 3.6.6 (v3.6.6:4cf1f54eb7, Jun 27 2018, 03:37:03) [MSC v.1900 64 bit (AMD64)] win32

Feature request

I created the iterator here below.
My iterator doesn't know its length at init() but only after execution of iter().
tqdm calls len() before iter() is called. So tqdm gets zero as a total.
Is it possible that tqdm could read len() after iter() ?

from tqdm import tqdm
import time

class MyIterator:

    def __init__(self):
        print("called __init__")
        self._search = {} # type: Dict[str, Any]
        self._total = 0 #: total number of results
        self._counter = 0 #: total counter of results

    def __iter__(self):
        print("called __iter__")
        self._search = list(range(12,32))
        self._total = len(self._search)
        self._counter = 0
        return self

    def __next__(self):
        if self._counter >= self._total:
            raise StopIteration
        self._counter += 1
        time.sleep(0.2)
        return self._search.pop(0)

    def __len__(self):
        print("called __len__")
        return self._total

for i in tqdm(MyIterator()):
    pass

Output:

called init
called len
0it [00:00, ?it/s]called iter
20it [00:04, 4.99it/s]

@casperdcl
Copy link
Sponsor Member

casperdcl commented Nov 30, 2019

I'm not sure this is standard - iterators which only have len() after iter()?

with tqdm(MyIterator()) as t:
    for i in t:
        if not t.total:
            t.total = len(t)
        pass

@casperdcl casperdcl self-assigned this Nov 30, 2019
@casperdcl casperdcl added the question/docs ‽ Documentation clarification candidate label Nov 30, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question/docs ‽ Documentation clarification candidate
Projects
None yet
Development

No branches or pull requests

2 participants