Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling Windows-specific exceptions in platform-independent way

Consider the following Python exception:

  [...]
    f.extractall()
  File "C:\Python26\lib\zipfile.py", line 935, in extractall
    self.extract(zipinfo, path, pwd)
  File "C:\Python26\lib\zipfile.py", line 923, in extract
    return self._extract_member(member, path, pwd)
  File "C:\Python26\lib\zipfile.py", line 957, in _extract_member
    os.makedirs(upperdirs)
  File "C:\Python26\lib\os.py", line 157, in makedirs
    mkdir(name, mode)
WindowsError: [Error 267] The directory name is invalid: 'C:\\HOME\\as\
\pypm-infinitude\\scratch\\b\\slut-0.9.0.zip.work\\slut-0.9\\aux'

I want to handle this particular exception - i.e., WindowsError with error number 267. However, I cannot simply do the following:

try:
    do()
except WindowsError, e:
    ...

Because that would not work on Unix systems where WindowsError is not even defined in the exceptions module.

Is there an elegant way to handle this error?

like image 842
Sridhar Ratnakumar Avatar asked Jul 31 '09 00:07

Sridhar Ratnakumar


3 Answers

If you need to catch an exception with a name that might not always exist, then create it:

if not getattr(__builtins__, "WindowsError", None):
    class WindowsError(OSError): pass

try:
    do()
except WindowsError, e:
    print "error"

If you're on Windows, you'll use the real WindowsError class and catch the exception. If you're not, you'll create a WindowsError class that will never be raised, so the except clause doesn't cause any errors, and the except clause will never be invoked.

like image 67
Glenn Maynard Avatar answered Sep 19 '22 13:09

Glenn Maynard


Here's my current solution, but I slightly despise using non-trivial code in a except block:

        try:
            f.extractall()
        except OSError, e:
            # http://bugs.python.org/issue6609
            if sys.platform.startswith('win'):
                if isinstance(e, WindowsError) and e.winerror == 267:
                    raise InvalidFile, ('uses Windows special name (%s)' % e)
            raise
like image 28
Sridhar Ratnakumar Avatar answered Sep 18 '22 13:09

Sridhar Ratnakumar


@Glenn Maynard 's answer does not allow debugging with pdb as the WindowsError builtin is not available in the debugger. This code block will work inside of the Python debugger and during normal execution:

import exceptions

if not getattr(exceptions, "WindowsError", None):
        class WindowsError(OSError): pass

This solution also works and avoids string literals and an import of the full exceptions library:

try:
    from exceptions import WindowsError
except ImportError:
    class WindowsError(OSError): pass
like image 21
Spitfire19 Avatar answered Sep 18 '22 13:09

Spitfire19