1

C# 背景

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

void LoadPlugin(string configFile)
{
    try
    {
        OpenAndReadConfig(configFile);
        DoMoreStuff();
    }
    catch (Exception ex)
    {
        throw new PluginException("Could not load plugin", ex);
    }
}

void OpenAndReadConfig(string configFile)
{
    try
    {
        OpenFile(configFile); // file does not exist
        DoStuff();
    }
    catch (Exception ex)
    {
        throw new ConfigurationException("Error reading configuration", ex);
    }
}

因此,如果某些代码调用LoadPlugin(@"non\existing\file.xml")您将拥有以下异常链,每个异常都保留其自己的堆栈跟踪:

  • PluginException:无法加载插件
    • ConfigurationException:读取配置时出错
      • FileNotFoundException: 找不到文件 'C:\non\existing\file.xml'

Python 问题

现在我正在使用 Python 2.6 上的一些库代码,我想实现类似的东西。在浏览了几个 SO 问题和博客/论坛之后,我想出了一个对我来说似乎足够好的解决方案,但由于我对 Python 的经验有限,我不知道是否有一些我遗漏的警告。我的想法是做这样的事情:

def open_and_read_config(config_file):
    try:
        open_file(config_file) # file does not exist
        do_stuff()
    except Exception, ex:
        ex.args = ('Error reading configuration',) + ex.args
        raise

def load_plugin(config_file):
    try:
        open_and_read_config(config_file)
        do_more_stuff()
    except Exception, ex:
        ex.args = ('Could not load plugin',) + ex.args
        raise

这样,我将保留原始异常的消息和回溯,同时能够添加上下文信息。我可以看到的一个缺点是,这只允许我以消息字符串的形式添加上下文信息,而不是新的异常类型(例如ConfigurationErroror PluginError)。此外,回溯将仅保留用于原始(最内部)异常。

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

4

1 回答 1

0

在 python 中,您只有一个回溯 - 用于最后创建的异常。如果要拆分回溯,则应使用此回溯和嵌套异常获取当前回溯 inexcept子句和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

...

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)
于 2013-06-07T17:15:54.377 回答