如何在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
? 我尝试下面的代码,但由于err
, ValueError
实例 ,不能被调用,失败:
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)
如果err
是从ValueError
派生的 ,这也会做正确的事情。 例如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的错误类。