[Tutor] KeyboardInterrupt handler
Michael P. Reilly
arcege@speakeasy.net
Sat, 2 Feb 2002 09:55:42 -0500
On Thu, Jan 31, 2002 at 05:15:01PM -0500, Lloyd Kvam wrote:
> Would it be practical to write a KeyboardInterrupt handler that "resumed" execution?
>
> Since the debugger seems to do this kind of thing, I assume the traceback object and
> its frame list could be used to accomplish a resume. (This is more idle curiosity than
> any real need.) Searching Google, my books, and the manual failed to come up with
> anything useful.
You can't restart Python from a frame (there is a version of Python
called "Microthreads" where you can handle continuations, but not in
Python itself).
The debugger doesn't do what you might think it does. There is a hook
in the Python interpreter that can run code. The debugger carefully
manages what code runs via this hook, and it can capture what exceptions
are being handled.
(cf. <URL: http://www.python.org/doc/current/lib/debugger-hooks.html>)
Typically, you'd write code that would reset what you are doing and
continue in whatever you were doing. Most importantly, if you have
something you are doing, then wrap it in a try-finally statement.
For example, if you had a command interpreter.
while 1:
try:
cmd = raw_input(prompt)
...
if cmd == 'change':
# call something that could potentially break if the user
# interrupted
make_change()
# catch the exception and reset the interpreter
except KeyboardInterrupt:
reset() # maybe just print so the prompt starts in the first column
def make_change():
try:
os.rename('file', 'file.temp')
inf = open('file.temp', 'rb')
outf = open('file', 'wb')
modify_file(inf, outf)
inf.close()
outf.close()
# if there is an error, then the files will still be open,
# and we will back-out the changes
# in this case, if the user types ^C, we move the files back and
# the exception gets back to the loop above to reset the command
finally:
if not outf.closed: # we didn't finish it
outf.close()
try:
os.remove('file')
except:
pass
inf.close()
os.rename('file.temp', 'file')
# otherwise, things completed successfully
Most database extensions will have provisions for rolling back
transactions. But you can do most everything in a similar way at
some level. I had to do this same exact thing ten years ago, writing
a bullet-proof command interpreter in Bourne shell. Using the
debugging mechanism is not going to help much to handle rolling back
operations like the above.
Your original question is: would it be practical. My response is: if
the user interrupted the program for a reason... should you resume at
the same place? That might help you answer your question.
-Arcege