I have a generator gen
, with the following properties:
- it's quite expensive to make it yield (more expensive than creating the generator)
- the elements take up a fair amount of memory
- sometimes all of the
__next__
calls will throw an exception, but creating the generator doesn't tell you when that will happen
I didn't implement the generator myself.
Is there a way to make the generator yield its first element (I will do this in a try/except), without having the generator subsequently start on the second element if I loop through it afterwards?
I thought of creating some code like this:
try:
first = next(gen)
except StopIterator:
return None
except Exception:
print("Generator throws exception on a yield")
# looping also over the first element which we yielded already
for thing in (first, *gen):
do_something_complicated(thing)
Solutions I can see which are not very nice:
- Create generator, test first element, create a new generator, loop through the second one.
- Put the entire for loop in a try/except; not so nice because the exception thrown by the yield is very general and it would potentially catch other things.
- Yield first element, test it, then reform a new generator from the first element and the rest of
gen
(ideally without extracting all ofgen
's elements into a list, since this could take a lot of memory).
For 3, which seems like the best solution, a nearly-there example would be the example I gave above, but I believe that would just extract all the elements of gen
into a tuple before we start iterating, which I would like to avoid.