如何在Python中使用自定义消息来引发同样的exception?

我有我的代码中的这个try块:

 try: do_something_that_might_raise_an_exception() except ValueError as err: errmsg = 'My custom error message.' raise ValueError(errmsg) 

严格来说,我实际上是在引发另一个 ValueError ,而不是由do_something...()引发的ValueError ,在这种情况下被称为err 。 如何将自定义消息附加到err ? 我尝试下面的代码,但由于errValueError 实例 ,不能被调用,失败:

 try: do_something_that_might_raise_an_exception() except ValueError as err: errmsg = 'My custom error message.' raise err(errmsg) 

更新: 对于Python 3,请检查Ben的答案


附加消息到当前的exception并重新提高它:(外部尝试/除了只是为了显示效果)

对于python 2.x其中x> = 6:

 try: try: raise ValueError # something bad... except ValueError as err: err.message=err.message+" hello" raise # re-raise current exception except ValueError as e: print(" got error of type "+ str(type(e))+" with message " +e.message) 

如果errValueError 派生的 ,这也会做正确的事情。 例如UnicodeDecodeError

请注意,您可以添加任何你喜欢的err 。 例如err.problematic_array=[1,2,3]


编辑: @Ducan点注释上面不能用python 3,因为.message不是ValueError的成员。 相反,你可以使用这个(有效的Python 2.6或更高版本或3.x):

 try: try: raise ValueError except ValueError as err: if not err.args: err.args=('',) err.args = err.args + ("hello",) raise except ValueError as e: print(" error was "+ str(type(e))+str(e.args)) 

EDIT2:

根据目的是什么,你也可以select在你自己的variables名下添加额外的信息。 对于python2和python3:

 try: try: raise ValueError except ValueError as err: err.extra_info = "hello" raise except ValueError as e: print(" error was "+ str(type(e))+str(e)) if 'extra_info' in dir(e): print e.extra_info 

我意识到这个问题已经有一段时间了,但是一旦你足够幸运,只能支持python 3.x,这真的成为美的东西:)

从…开始

我们可以使用raise来链接exception。

 try: 1 / 0 except ZeroDivisionError as e: raise Exception('Smelly socks') from e 

在这种情况下,你的调用者将会捕捉的exception有我们提出exception的地方的行号。

 Traceback (most recent call last): File "test.py", line 2, in <module> 1 / 0 ZeroDivisionError: division by zero The above exception was the direct cause of the following exception: Traceback (most recent call last): File "test.py", line 4, in <module> raise Exception('Smelly socks') from e Exception: Smelly socks 

注意底部的exception只有我们提出exception的地方有堆栈跟踪。 您的调用者仍然可以通过访问它们捕获的exception的__cause__属性来获取原始exception。

with_traceback

或者你可以使用with_traceback 。

 try: 1 / 0 except ZeroDivisionError as e: raise Exception('Smelly socks').with_traceback(e.__traceback__) 

使用这种forms,你的调用者将会捕获的exception具有从原始错误发生的地方回溯。

 Traceback (most recent call last): File "test.py", line 2, in <module> 1 / 0 ZeroDivisionError: division by zero During handling of the above exception, another exception occurred: Traceback (most recent call last): File "test.py", line 4, in <module> raise Exception('Smelly socks').with_traceback(e.__traceback__) File "test.py", line 2, in <module> 1 / 0 Exception: Smelly socks 

注意最底层的exception是我们执行无效分割的行以及我们重新规则exception的行。

 try: try: int('a') except ValueError as e: raise ValueError('There is a problem: {0}'.format(e)) except ValueError as err: print err 

打印:

 There is a problem: invalid literal for int() with base 10: 'a' 

似乎所有的答案都添加到e.args [0]的信息,从而改变现有的错误信息。 扩展参数元组是否有缺点? 我认为可能的好处是,如果需要parsing该string,可以单独保留原始错误消息; 如果你的自定义error handling产生了几个消息或错误代码,那么你可以添加多个元素到元组,如果是以编程方式parsingtraceback的情况(如通过系统监视工具)。

 ## Approach #1, if the exception may not be derived from Exception and well-behaved: def to_int(x): try: return int(x) except Exception as e: e.args = (e.args if e.args else tuple()) + ('Custom message',) raise >>> to_int('12') 12 >>> to_int('12 monkeys') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 3, in to_int ValueError: ("invalid literal for int() with base 10: '12 monkeys'", 'Custom message') 

要么

 ## Approach #2, if the exception is always derived from Exception and well-behaved: def to_int(x): try: return int(x) except Exception as e: e.args += ('Custom message',) raise >>> to_int('12') 12 >>> to_int('12 monkeys') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 3, in to_int ValueError: ("invalid literal for int() with base 10: '12 monkeys'", 'Custom message') 

你能看到这种方法的缺点吗?

这是我用来修改Python 2.7和3.x中的exception消息的function,同时保留原始的回溯。 它需要six

 def reraise_modify(caught_exc, append_msg, prepend=False): """Append message to exception while preserving attributes. Preserves exception class, and exception traceback. Note: This function needs to be called inside an except because `sys.exc_info()` requires the exception context. Args: caught_exc(Exception): The caught exception object append_msg(str): The message to append to the caught exception prepend(bool): If True prepend the message to args instead of appending Returns: None Side Effects: Re-raises the exception with the preserved data / trace but modified message """ ExceptClass = type(caught_exc) # Keep old traceback traceback = sys.exc_info()[2] if not caught_exc.args: # If no args, create our own tuple arg_list = [append_msg] else: # Take the last arg # If it is a string # append your message. # Otherwise append it to the # arg list(Not as pretty) arg_list = list(caught_exc.args[:-1]) last_arg = caught_exc.args[-1] if isinstance(last_arg, str): if prepend: arg_list.append(append_msg + last_arg) else: arg_list.append(last_arg + append_msg) else: arg_list += [last_arg, append_msg] caught_exc.args = tuple(arg_list) six.reraise(ExceptClass, caught_exc, traceback) 

目前的答案对我来说并不好,如果没有重新捕获exception,附加的消息就不会显示出来。

但是,像下面这样做,不pipe是否重新捕获exception,都会保持跟踪并显示附加消息。

 try: raise ValueError("Original message") except ValueError as err: t, v, tb = sys.exc_info() raise t, ValueError(err.message + " Appended Info"), tb 

(我用Python 2.7,没有在Python 3中尝试过)

Python 3内置的exception有strerror字段:

 except ValueError as err: err.strerror = "New error message" raise err 

此代码模板应该允许您用自定义消息引发exception。

 try: raise ValueError except ValueError as err: raise type(err)("my message") 

如果你想自定义错误types,你可以做的一件简单的事情就是定义一个基于ValueError的错误类。