Resume after exception

R

Richard Lewis

Hi there,

Is it possible to have an 'except' case which passes control back to the
point after the exception occurred?

e.g.

# a function to open the file
# raises FileLockedException is file contains 'locked' information
def open_file(file_name):
f = file(file_name, 'r')
{read first line for file lock info}
if first_line == "FILE LOCKED":
raise FileLockedException(lock_user, lock_timestamp)
{read remainder of file}
return True

# elsewhere in a user interface module
def open_command():
try:
open_file("foo.bar")
except FileLockException, X:
ans = tkMessageBox.askyesno(title="File Locked", message="File
locked by '" + X.user + "' on " + X.time_stamp + "\nContinue
anyway?")
if ans == tkMessageBox.YES:
# return control to the remainder of the open_file function.
How?
else:
return False

Any ideas?

Cheers,
Richard
 
D

Dan Sommers

Hi there,
Is it possible to have an 'except' case which passes control back to the
point after the exception occurred?

Not that I can think of.

[ example of "interrupting" a file-reading function in order to ask the
user if they really want to read a locked file ]

I would rewrite that this way (untested, and without error checking):

def open_file(file_name, read_if_locked=False):
f = file(file_name)
[read first line]
if first_line == "FILE LOCKED" and read_if_locked == FALSE:
return False
[read the rest]
return True

def open_command():
if open_file("foo.bar") == False:
[ask the user what to do]
if ans == tkMessageBox.YES:
open_file("foo.bar", True )

Regards,
Dan
 
P

peterbe

Why does the first function return True? Shouldn't it return the file
content? That's at least what the function name implies.
You call the second function open_command() which returns a boolean.
Feels wrong.

Where you have written "How?" I suggest that you replace that by:
return open_file("foo.bar", 1)

and change open_file() to look something like this:
def open_file(file_name, ignore_lock=False):
f = file(file_name, 'r')
{read first line for file lock info}
if first_line == "FILE LOCKED" and not ignore_lock:
raise FileLockedException(lock_user, lock_timestamp)
{read remainder of file}
return True
 
P

Peter Hansen

Richard said:
Is it possible to have an 'except' case which passes control back to the
point after the exception occurred?

Basically no, although I could imagine some gross hack with the frame
info and some bytecode hacks that effect a "goto". Basically the stack
frame gets unwound to the point where the exception is caught. If you
need recoverability, write your open_file function to be resumable in
some way.

Note that you could easily (perhaps) implement this as a callable
object, with the required state stored internally, and make the result
almost indistinguishable from what you are asking for:

I could imagine an API allowing something like this:

open_file = RecoverableOpenFileThingy()

while not open_file.completed:
try:
open_file("foo.bar")
except FileLockException, ex:
# blah blah
if ans != tkMessageBox.YES:
open_file.completed = True

But since your open_file() doesn't seem likely to be doing anything
particularly complicated, I really doubt you need the complexity of a
special class here. Just stick the relevant code inside a loop, much
like that above, and break out of the loop when things succeed.

(What internal state do you think the open_file procedure would have to
maintain, which you would be trying to resume? If you are just going to
go back to the beginning of it and try again, you don't need anything
like what you asked for, just a regular loop.)
 
M

metawilm

Richard Lewis schreef:
Is it possible to have an 'except' case which passes control back to the
point after the exception occurred?

No, not in Python. The concept has however been discussed, under the
name "resumable exceptions".

http://www.google.com/search?num=100&q="resumable+exceptions"+site:python.org

An excellent article about the concept was written by Kent Pitman:

"Condition Handling in the Lisp Language Family"
http://www.nhplace.com/kent/Papers/Condition-Handling-2001.html

Common Lisp is a language that does have the feature. Your code would
be written in Lisp like below. When the function notices the file is
locked, it will raise an exception. Now imagine there are two ways to
solve the problem: 1) read the file anyway, despite the lock; 2) clear
the lock and read the file. Or reading the file could be cancelled.
These three possible ways to continue the execution are set up by
"restart-case". (So this is actually a generalization of your request,
in that instead of "just continueing", you can direct the way of
continuing)

(defun read-unlocked-file (file-name)
(with-open-file (f file-name)

(when (string= (read-line f) "FILE LOCKED")
(let ((user "lock-user")
(timestamp 123))
(restart-case (error 'file-locked :name file-name
:user user :timestamp timestamp)
(continue () :report "Continue reading the locked file.")
(clear-lock () :report "Clear the lock and continue reading"
(warn "clearing lock..."))
(abort () :report "Abort reading the file."
(return-from read-unlocked-file)))))

(warn "reading remainder of file...")
t))

When reading a locked file, you end up with this message:

CL-USER(31): (read-unlocked-file "file.txt")
Error: File file.txt was locked by lock-user at time 123.
[condition type: FILE-LOCKED]

Restart actions (select using :continue):
0: Continue reading the locked file.
1: Clear the lock and continue reading
2: Abort reading the file.
3: Return to Top Level (an "abort" restart).
4: Abort entirely from this process.

Note the three first "restart actions" are the ones we just defined
inside "read-unlocked-file". Let's continue execution by clearing the
lock (restart number 1):

[1] CL-USER(32): :continue 1
Warning: clearing lock...
Warning: reading remainder of file...
T

If Python had restarts, in your example you would set up code that,
depending on whether the user clicked "abort" or "continue" in the
dialog, automatically invokes the corresponding restart to either
continue or abort the calculation.

Restarts are pretty cool. Maybe Stackless Python could support it
fairly easily, restarts basically being named continuations?


- Willem
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top