【问题标题】:python3 re-raising an exception with custom attribute?python3使用自定义属性重新引发异常?
【发布时间】:2013-04-05 15:50:07
【问题描述】:

这是我需要移植的 python2 代码:

try:
  do_something_with_file(filename)

except:
  exc_type, exc_inst, tb = sys.exc_info()
  exc_inst.filename = filename
  raise exc_type, exc_inst, tb

使用上面的代码,我可以通过检查异常是否具有“文件名”属性来获取有问题的输入文件的整个异常。

然而,python3 的 raise 已经改变。这就是 2to3 给我的上述代码:

except Exception as e:
  et, ei, tb = sys.exc_info()
  e.filename = filename
  raise et(e).with_traceback(tb)

这给了我另一个错误,我不认为文件名属性被保留:

in __call__
    raise et(e).with_traceback(tb)
TypeError: function takes exactly 5 arguments (1 given)

我只想用一些信息透明地传递异常以跟踪输入文件。我想念 python2 的 raise [exception_type[,exception_instance[,traceback]]] - 我如何在 python3 中做到这一点?

【问题讨论】:

    标签: python python-3.x


    【解决方案1】:

    可以设置__traceback__属性:

    except Exception as e:
        et, ei, tb = sys.exc_info()
        ei.filename = filename
        ei.__traceback__ = tb
        raise ei
    

    或直接在旧实例上调用.with_traceback()

    except Exception as e:
        et, ei, tb = sys.exc_info()
        ei.filename = filename
        raise ei.with_traceback(tb)
    

    不过,traceback已经自动附加了,不需要重新附加,真的。

    raise statement documentation

    当引发异常并作为可写的__traceback__ 属性附加到它时,通常会自动创建回溯对象。

    在这种特定情况下,也许您想要一个不同的例外,有上下文?

    class FilenameException(Exception):
        filename = None
        def __init__(self, filename):
            super().__init__(filename)
            self.filename = filename
    
    try:
        something(filename)
    except Exception as e:
        raise FilenameException(filename) from e
    

    这将创建一个链式异常,如果未捕获两个异常都将被打印,并且原始异常以newexception.__context__ 的形式提供。

    【讨论】:

    • 谢谢!但我刚用谷歌搜索发现raise ei.with_traceback(tb):D
    • @thkang:见docs.python.org/3/reference/…,两者都有效。
    • 谢谢,我认为最好的办法是用 python3 的 raise ... from ... 样式重写每个异常处理代码。
    • @thkang:只要你创建一个new异常,from语法就很好了。
    【解决方案2】:

    你不需要做任何事情;在 Python 3 中,重新引发的异常会自动从它们最初引发的位置获得完整的追溯。

    try:
      do_something_with_file(filename)
    except Exception as exc_inst:
      exc_inst.filename = filename
      raise exc_inst
    

    这是因为PyErr_NormalizeException 在捕获except 语句中的异常时适当地设置了__traceback__ 属性;见http://www.python.org/dev/peps/pep-3134/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-23
      • 2016-03-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多