Summary
What I am after is a way of determining if the generator is "currently running".
Details
My definition of "currently running" is:
- The generator code has begun execution (i.e.,
nextor.send(None)or some other iteration operation such as a for loop, has previously been executed on the generator, AND - the generator was not previously exhausted/closed (again note that for the above generator,
.throw(some_error)is caught and will not exhaust the generator since some new loop is started; without a loop oryield froma handled error will usually exhaust the generator).
I understand that there is not a way (or at least, a trivially easy way) to "peek" ahead in a generator and find out if it will raise StopIteration at the next iteration. This is antithetical to the nature of the generator and is NOT what I am after.
Example
Say I have some generator, g created by some generator function, f:
def f():
'''Lots of 1s.'''
print('I am now running.')
while True:
try:
signal = yield 1
if signal:
break
except GeneratorExit:
raise # important so that closing the generator doesn't cause a RuntimeError
except Exception:
print('caught exception!')
We can "initialize" the generator this way:
>>> g = f()
>>> next(g)
I am now running.
1
# OR:
>>> g.send(None) # equivalent to next(g)
I am now running.
1
If I send anything truthy into the generator, the StopIteration error is raised (e.g., g.send('foo')). Alternatively, if I call g.close(), and then do next(g), I will also get StopIteration. If I throw any errors with g.throw(e), the generator will continue. This is all as expected.
What I'd like to be able to do is something like the following, which shows whether or not this generator is running:
>>> g=f()
>>> g.running
False
>>> g.send(None)
I am now running.
1
>>> g.running
True
>>> g.close()
>>> g.running
False
I have provided one possible approach in an answer. However, I think there has to be a better way.