在课堂__exit__中获取errno

时间:2018-01-05 11:37:02

标签: python exception-handling contextmanager

我有一个类在__init__创建当前目录的备份,并在出现任何问题时恢复备份。我认为对于上下文管理器来说这将是一个很好的工作:

class Directory:
    def __init__(self):
        self._create_backup()

    ...

    def __enter__(self):
        return self

    def __exit__(self, exit_type, exit_value, exit_traceback):
        if exit_type is KeyboardInterrupt:
            self._restore_from_backup()
            sys.exit("Caught system interrupt. Aborting.")
            # This is actually more complicated, but for the sake of MCVE

        # Handle other exceptions here

        else:
            self._delete_backup()

现在,我想获取异常的errno属性,以检查它是否与errno.EPERM匹配,但我无法弄清楚如何。

我不想在exit_value上使用像正则表达式匹配这样的hacky解决方案。

2 个答案:

答案 0 :(得分:3)

exit_value是类exc_type的实例。您应该可以执行以下操作:

if isinstance(exit_value, OSError):
    print(exit_value.errno)

如果要捕获定义errno的其他异常,您还可以执行以下操作:

errno = getattr(exit_value, 'errno', None)
if errno is not None:
    print(errno)

我可能会使用后者,因为定义名为errno的属性的任何异常都可以与errno.E*常量进行比较。

答案 1 :(得分:1)

IOError实例具有属性errno,因此您需要以下内容:

def __exit__(self, exit_type, exit_value, exit_traceback):
    if exit_type is KeyboardInterrupt:
        self._restore_from_backup()
        sys.exit("Caught system interrupt. Aborting.")
        # This is actually more complicated, but for the sake of MCVE
    elif exit_type is IOError:
        if exit_value.errno == errno.EPERM:
            # Handle your desired case
    # Handle other exceptions here

    else:
        self._delete_backup()

编辑:我假设OP导入errno,因为他提到在问题中使用它,但当然在errno模块可用之前需要以下行

import errno