我来自一个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")
,您将拥有以下异常链,每个异常都会保留自己的堆栈跟踪:
现在我正在使用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
这样我就可以保留原始异常的消息和回溯,同时能够添加上下文信息。我可以看到的一个缺点是,这只允许我在消息字符串的形式上添加上下文信息,而不是新的异常类型(例如ConfigurationError
或PluginError
)。此外,仅对原始(最内层)异常保留回溯。
那么,还有什么我想念的吗?你有什么理由建议不要使用这种方法吗?
答案 0 :(得分:0)
在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
...
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)