Python Generators and yield : How to know which line the program is at
Suppose you have a simple generator in Python like this :
Update :
def f(self):
customFunction_1(argList_1)
yield
customFunction_2(argList_2)
yield
customFunction_3(argList_3)
yield
...
I call f() 开发者_StackOverflow中文版in another script like :
h=f()
while True:
try:
h.next()
sleep(2)
except KeyboardInterrupt:
##[TODO] tell the last line in f() that was executed
Is there a way that I can do the [TODO] section above? that is knowing the last line in f() that was executed before keyboardInterrupt occurred ?
You can use enumerate() to count:
def f():
...
yield
...
yield
...
for step, value in enumerate(f()):
try:
time.sleep(2)
except KeyboardInterrupt:
print(step) # step holds the number of the last executed function
(because in your example yield
does not yield a value, value
will of course be None)
Or very explicit using a verbose indication:
def f():
...
yield 'first function finished'
...
yield 'almost done'
...
for message in f():
try:
time.sleep(2)
except KeyboardInterrupt:
print(message)
If you want to know the line number for debugging purposes then in CPython you can use h.gi_frame.f_lineno
. This is the line which will be executed next and is 1-indexed. I'm not sure if this works on Python implementations other than CPython.
h=f()
while True:
try:
h.next()
sleep(2)
except KeyboardInterrupt:
print h.gi_frame.f_lineno - 1 # f_lineno is the line to be executed next.
If you don't want to know this for debugging purposes then Remi's enumerate
solution is far cleaner.
Why don't you yield i from f() and use that ?
val = h.next()
def f(self):
sleep(10)
yield
sleep(10)
yield
sleep(10)
yield
h=f()
while True:
try:
h.next()
except KeyboardInterrupt:
stack_trace = sys.exc_info()[2] # first traceback points into this function where the exception was caught
stack_trace = stack_trace.tb_next # now we are pointing to where it happened (in this case)
line_no = stack_trace.tb_lineno # and here's the line number
del stack_trace # get rid of circular references
I moved the call to sleep()
into f
as this only works if the exception happens inside f()
.
精彩评论