Updated: modern Sage raises an AlarmInterrupt
instead of a KeyboardInterrupt
, so you can catch it explicitly instead. That's a much cleaner solution than having to dig around inside a KeyboardInterrupt
message.
Also, it's probably a better idea to use cancel_alarm()
than alarm(0)
, which was apparently never officially supported.
Sure. While I would have made it a little more explicit, the KeyboardInterrupt generated by alarm does contain information that a typical KeyboardInterrupt doesn't, in the .args and .message attributes. For example, control-C in the following
try:
sleep(5)
except KeyboardInterrupt as KI:
print 'args=',KI.args
print 'message=', KI.message
produces
^Cargs= ()
message=
but adding alarm(2)
before executing it produces:
args= ('computation timed out because alarm was set for 2 seconds',)
message= computation timed out because alarm was set for 2 seconds
So one way to take advantage of this would be through something like this:
while True:
alarm(3)
try:
print 'sleeping..'
sleep(5)
except KeyboardInterrupt as KI:
if KI.message.startswith("computation timed out"):
print 'timed out!'
continue
else:
# not a timeout, so break
print 'manual exit!'
alarm(0)
break
alarm(0)
which gives
sleeping..
timed out!
sleeping..
timed out!
sleeping..
timed out!
sleeping..
^Cmanual exit!
I tend to wrap this stuff up in decorators, but in this case mine is nested three deep so it's probably overkill for the problem, because it makes it look more complicated than it really is.