简体   繁体   中英

How would you catch python Exception inside an except clause

How would you catch exception within exception in python?

Consider the following case

bak_filename = filename + ".bak"
#This try is needed because if bak_filename existed, rename will fail
try:
   os.rename(filename, bak_filename)
except WindowsError:
   #However, os.remove may still fail e.g. file in use. How would you handle this exception within except clause ?
   #try and except around this os.remove?  
   os.remove(bak_filename)

   os.rename(filename, bak_filename)

Any thought of:

  1. Rewriting to avoid double try ?

  2. Not necessarily this example, but in some case we cannot rewrite, how would you handle double try ?

A solution to avoid all this exception wrapping would be to useshutil.move

shutil.move(filename, bak_filename)

If the destination already exists but is not a directory, it may be overwritten depending on os.rename() semantics.

If the destination is on the current filesystem, then os.rename() is used. Otherwise, src is copied to dst using copy_function and then removed. In case of symlinks, a new symlink pointing to the target of src will be created in or as dst and src will be removed.

So it basically does what you're trying to do, but in a library which is available on all python distros.

Note that the performance may be bad if the file is big and the target file exists and os.rename refuses to overwrite it (completely depends on the operating system but for instance Windows will refuse to rename over an existing file), because the fallback when os.rename throws OSError is copying the source then deleting. The implementation doesn't try to remove the file then rename again, because if rename fails, Python assumes that we're trying to rename across filesystems, and a copy+delete is in order in that case (this is exactly how Unix mv works).

try:
    os.rename(src, real_dst)
except OSError:
    if os.path.islink(src):
        ...
    else:
        copy_function(src, real_dst)
        os.unlink(src)

To workaround that possible file existence, a prior os.remove call wrapped in a try/except OSError statement could be done.

try:
   os.remove(bak_filename)
except OSError:
   pass
shutil.move(filename, bak_filename)  # or os.rename(filename, bak_filename)

Of course if bak_filename is locked/not deletable, an exception can still be raised by shutil.mode . Also note that if we tried to delete the target file, os.rename will be as good as shutil.move . If the target file could not be deleted, the operation can't succeed anyway.

You can read more on Exception Chaining . But, that's for Python 3

In Python 2, you can store your exception in a variable, then raise it again explicitly like this:

try:
    do something
except Exception as e:
    try:
        do something again
    except:
        pass
    raise e

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM