Resume after exception

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Richard Lewis

    Resume after exception

    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 FileLockedExcep tion 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 FileLockedExcep tion(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 FileLockExcepti on, X:
    ans = tkMessageBox.as kyesno(title="F ile Locked", message="File
    locked by '" + X.user + "' on " + X.time_stamp + "\nContinue
    anyway?")
    if ans == tkMessageBox.YE S:
    # return control to the remainder of the open_file function.
    How?
    else:
    return False

    Any ideas?

    Cheers,
    Richard
  • Dan Sommers

    #2
    Re: Resume after exception

    On Tue, 14 Jun 2005 10:09:30 +0100,
    "Richard Lewis" <richardlewis@f astmail.co.uk> wrote:
    [color=blue]
    > Hi there,
    > Is it possible to have an 'except' case which passes control back to the
    > point after the exception occurred?[/color]

    Not that I can think of.

    [ example of "interrupti ng" 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.YE S:
    open_file("foo. bar", True )

    Regards,
    Dan

    --
    Dan Sommers
    <http://www.tombstoneze ro.net/dan/>

    Comment

    • peterbe@gmail.com

      #3
      Re: Resume after exception

      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=Fal se):
      f = file(file_name, 'r')
      {read first line for file lock info}
      if first_line == "FILE LOCKED" and not ignore_lock:
      raise FileLockedExcep tion(lock_user, lock_timestamp)
      {read remainder of file}
      return True

      Comment

      • Peter Hansen

        #4
        Re: Resume after exception

        Richard Lewis wrote:[color=blue]
        > Is it possible to have an 'except' case which passes control back to the
        > point after the exception occurred?[/color]

        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 indistinguishab le from what you are asking for:

        I could imagine an API allowing something like this:

        open_file = RecoverableOpen FileThingy()

        while not open_file.compl eted:
        try:
        open_file("foo. bar")
        except FileLockExcepti on, ex:
        # blah blah
        if ans != tkMessageBox.YE S:
        open_file.compl eted = 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.)

        Comment

        • metawilm@gmail.com

          #5
          Re: Resume after exception

          Richard Lewis schreef:[color=blue]
          > Is it possible to have an 'except' case which passes control back to the
          > point after the exception occurred?[/color]

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



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

          "Condition Handling in the Lisp Language Family"


          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

          Comment

          Working...