4

I often read that in python "it is easier to ask for forgiveness then for permission", so it is sometimes considered better to use try except instead of if.

I often have statements like

if (not os.path.isdir(dir)):
    os.mkdir(dir).

The likely replacement would be

try:
    os.mkdir(dir)
except OSError:
    pass.

However I would like to be more specific and only ignore the errno.EEXIST, as this is the only error that is expected to happen and I have no idea what could happen.

try:
    os.mkdir(dir)
except OSError:
    if(OSError.errno != errno.EEXIST):
        raise
    else:
        pass.

Seems to do the trick. But this is really bulky and will 'pollute' my code and reduce readability if I need plenty of these code-blocks. Is there a pythonic way to do this in Python 2.X? What is the standard procedure to handle such cases?

edits:

  • use raise instead raise OSerror as pointed out by @Francisco Couzo
  • I use Python 2.7
4
  • 1
    Just do raise, not raise OSError so you don't lose the context of the exception Commented Oct 23, 2016 at 7:34
  • 1
    You could just catch FileExistsError: except FileExistsError: pass Commented Oct 23, 2016 at 7:35
  • Dup of: stackoverflow.com/questions/20790580/… Commented Oct 23, 2016 at 7:58
  • 1
    No need for else: pass, that's redundant. Commented Oct 24, 2016 at 21:20

3 Answers 3

1

I just stumbled across the probably most elegant solution: creating the ignored context manager:

import errno
from contextlib import contextmanager

@contextmanager
def ignorednr(exception, *errornrs):
    try:
        yield
    except exception as e:
        if e.errno not in errornrs:
            raise
        pass


with ignorednr(OSError, errno.EEXIST):
     os.mkdir(dir)

This way I just have the ugly job of creating the context manager once, from then on the syntax is quite nice and readable.

The solution is taken from https://www.youtube.com/watch?v=OSGv2VnC0go.

Sign up to request clarification or add additional context in comments.

Comments

0

If you are calling it multiple times with different args, put it in a function:

def catch(d, err):
    try:
        os.mkdir(d)
    except OSError as e:
        if e.errno != err:
            raise

Then call the function passing in whatever args:

 catch(, "foo", errno.EEXIST)

You could also allow the option of passing passing multiple errno's if you wanted more:

def catch(d, *errs):
    try:
        os.mkdir(d)
    except OSError as e:
        if e.errno not in errs:
            raise

catch("foo", errno.EEXIST, errno.EPERM)

Comments

0

This example is for exception OSError : 17, 'File exists'

import sys
try:
    value = os.mkdir("dir")
except:
    e = sys.exc_info()[:2]
    e = str(e)
    if "17" in e:
        raise OSError #Perform Action
    else:
        pass   

Just change the number 17 to your exception number. You can get a better explanation at this link.

1 Comment

I think my question already provides a better answer, it is shorter and doesn't use the explicit number. I read the numbers might differ depending on the system so errno.EEXIST is better and also more readable.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.