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

时间:2016-10-23 07:31:59

标签: python error-handling errno

我经常在python中读到“请求宽恕然后获得许可更容易”,因此有时候使用try except代替if会更好。

我经常有像

这样的陈述
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.
似乎要做的伎俩。但是这真的很笨重,如果我需要大量的代码块,它会“污染”我的代码并降低可读性。在Python 2.X中有没有pythonic方法来做到这一点?处理此类案件的标准程序是什么?

编辑:

  • 使用raise而不是像@Francisco Couzo所指出的那样提出OSerror
  • 我使用Python 2.7

3 个答案:

答案 0 :(得分:0)

此示例适用于例外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即可。您可以通过[link https://docs.python.org/2/library/sys.html#sys.exc_info][1]

获得更好的解释

答案 1 :(得分:0)

如果您使用不同的args多次调用它,请将其放在函数中:

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

然后调用函数传入任何args:

 catch(, "foo", errno.EEXIST)

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

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)

答案 2 :(得分:0)

我偶然发现了最优雅的解决方案:创建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