简体   繁体   中英

Catch specific exceptions with try…except

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)

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