I have some code to rename a whole bunch of files and move them to a new directory using os.rename()
. Its fairly simple, nothing flashy. It worked until I had some overlap in batches and there were duplicate files, this raised a WindowsError
. Since the code worked in all otherways, I did
try:
os.rename(...)
except WindowsError:
print "Duplicate file {}".format(fileName)
This worked fine, except that it implies that all WindowsError
s are from duplicate files. The result was that when another aspect of my script broke, it failed essentially silently.
How can I employ try...except
to catch only specific exceptions? If its not possible, what workarounds exist?
According to the documentation:
"The errno
value maps the winerror
value to corresponding errno.h
values."
Because of this, you should be able to distinguish between different Windows errors by using errno
.
Example:
try:
fp = open("nother")
except IOError as e:
print e.errno
print e
I wrote a context manager to suppress OSError
based on errno
value. Here's that context manager, just rewritten a little bit to catch WinError
instead.
Your example code prints a message when the error occurs, but this won't print anything; it silently suppresses the exception.
I haven't tested this because I don't have Windows handy, but I tested the original and this is a trivial edit. Let me know if you have any trouble with this.
The .__exit__()
method function gets information about any received exceptions, and if it returns True
the exception is suppressed; if it returns False
the exception is raised as normal. Thus this only suppresses the exception if the type matches (it was a WinError
exception) and the .errno
attribute matches the saved self.errno
value.
class suppress_winerror(object):
def __init__(self, errno):
self.errno = errno
def __enter__(self):
return self
def __exit__(self, e_type, e_val, e_tb):
if e_type is not WinError:
return False
if e_val.errno != self.errno:
return False
return True
Example of how to use this. I'm assuming that the windows error code is being mapped onto errno.EEXIST
, the errno
code for "file already exists". Obviously if I got this wrong, you should put the correct error code instead.
import errno
with suppress_winerror(errno.EEXIST):
os.rename(old_fname, new_fname)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With