使用添加的上下文信息在Python2.x中重新引发异常 C#背景

使用添加的上下文信息在Python2.x中重新引发异常 C#背景,python,exception,exception-handling,python-2.x,Python,Exception,Exception Handling,Python 2.x,我来自一个C#上下文,您可以捕获一个异常并抛出一个新异常,包括作为内部异常的原始异常。这样你就可以有这样的东西: void LoadPlugin(字符串配置文件) { 尝试 { OpenAndReadConfig(配置文件); DoMoreStuff(); } 捕获(例外情况除外) { 抛出新插件异常(“无法加载插件”,ex); } } void OpenAndReadConfig(字符串配置文件) { 尝试 { OpenFile(configFile);//文件不存在 DoStuff(); }

我来自一个C#上下文,您可以捕获一个异常并抛出一个新异常,包括作为内部异常的原始异常。这样你就可以有这样的东西:

void LoadPlugin(字符串配置文件)
{
尝试
{
OpenAndReadConfig(配置文件);
DoMoreStuff();
}
捕获(例外情况除外)
{
抛出新插件异常(“无法加载插件”,ex);
}
}
void OpenAndReadConfig(字符串配置文件)
{
尝试
{
OpenFile(configFile);//文件不存在
DoStuff();
}
捕获(例外情况除外)
{
抛出新的ConfigurationException(“读取配置时出错”,ex);
}
}
因此,如果一些代码调用
LoadPlugin(@“non\existing\file.xml”)
您将拥有以下异常链,每个异常保留其自己的堆栈跟踪:

  • 插件异常:无法加载插件
    • ConfigurationException:读取配置时出错
      • FileNotFoundException:找不到文件“C:\non\existing\file.xml”
Python问题 现在,我正在处理Python 2.6上的一些库代码,我希望实现类似的功能。在浏览了几个SO问题和博客/论坛之后,我提出了一个对我来说似乎足够好的解决方案,但由于我使用Python的经验有限,我不知道是否有一些我遗漏的注意事项。我的想法是这样做:

def open_和_read_配置(配置文件):
尝试:
打开_文件(配置_文件)#文件不存在
做某事
除例外情况外,例如:
ex.args=('Error reading configuration',)+ex.args
提升
def加载插件(配置文件):
尝试:
打开并读取配置(配置文件)
做更多的事情
除例外情况外,例如:
ex.args=('无法加载插件',)+ex.args
提升
这样,我将保留原始异常的消息和回溯,同时能够添加上下文信息。我看到的一个缺点是,这只允许我以消息字符串的形式添加上下文信息,而不允许添加新的异常类型(例如
ConfigurationError
PluginError
)。此外,回溯将仅为原始(最内层)异常保留


那么,我还缺什么吗?有什么理由不建议使用这种方法吗?

在python中,对于上次创建的异常,只有一个回溯。如果要拆分回溯,应在
except
子句和
raise
新异常中获取当前回溯,并使用此回溯和嵌套异常的适当类型,即:

import traceback
class TracebackableException(Exception):
    def __init__(self, message, traceback, inner=None):
        self.message = message
        self.traceback = traceback
        self.inner = inner

class ConfigurationException(TracebackableException): pass
class PluginException(TracebackableException): pass


这不是问题。您可以创建自己的异常子类,其行为与C#exception相同。我相信在python3中,这类事情变得更容易做了。
def open_and_read_config(config_file):
    try:
        open_file(config_file) # file does not exist
        do_stuff()
    except IOError, ex:
        raise ConfigurationException("Cannot load config", traceback.format_exc(), ex)

def load_plugin(config_file):
    try:
        open_and_read_config(config_file)
        do_more_stuff()
    except Exception, ex:
        raise PluginException("Cannot load plugin", traceback.format_exc(), ex)