Reputation: 1982
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 :
Rewriting to avoid double try?
Not necessarily this example, but in some case we cannot rewrite, how would you handle double try ?
Upvotes: 1
Views: 238
Reputation: 140307
A solution to avoid all this exception wrapping would be to use shutil.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.
Upvotes: 1
Reputation: 1
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
Upvotes: 0