Pythonic 异常处理:只捕获特定的 errno

Pythonic exception handling: only catching specific errno

我经常在 python "it is easier to ask for forgiveness then for permission" 中看到它,因此有时认为使用 try exceptif 更好。

我经常有这样的说法

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

可能的替代品是

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

不过,我想说得更具体一些,只忽略 errno.EEXIST,因为这是预期会发生的唯一错误,我不知道会发生什么。

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

似乎可以解决问题。但这真的很笨重,如果我需要大量这些代码块,将会 'pollute' 我的代码并降低可读性。在 Python 2.X 中是否有 pythonic 方法来执行此操作?处理此类案件的标准程序是什么?

编辑:

这个例子是例外情况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   

只需将数字 17 更改为您的例外编号。您可以在 this link.

获得更好的解释

如果你用不同的参数多次调用它,把它放在一个函数中:

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

然后调用传入任意参数的函数:

 catch(, "foo", errno.EEXIST)

如果你想要更多,你也可以允许传递多个错误号的选项:

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)

我偶然发现了可能是最优雅的解决方案:创建 ignored 上下文管理器:

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)

这样我就完成了一次创建上下文管理器的丑陋工作,从那时起语法就非常好并且可读了。

解决方案取自https://www.youtube.com/watch?v=OSGv2VnC0go