How do I manually throw/raise an exception in Python?
在您的信息中具体说明,例如:raise ValueError('A very specific bad thing happened.')
不引发一般异常
避免引发一般异常。要捕获它,您必须捕获它的子类的所有其他更具体的异常。
问题1:隐藏bugraise Exception('I know Python!') # Don't! If you catch, likely to hide bugs.
例如:def demo_bad_catch():
try:
raise ValueError('Represents a hidden bug, do not catch this')
raise Exception('This is the exception you expect to handle')
except Exception as error:
print('Caught this error: ' + repr(error))
>>> demo_bad_catch()
Caught this error: ValueError('Represents a hidden bug, do not catch this',)
问题2:抓不到
更具体的捕获不会捕获一般异常:def demo_no_catch():
try:
raise Exception('general exceptions not caught by specific handling')
except ValueError as e:
print('we will not catch exception: Exception')
>>> demo_no_catch()
Traceback (most recent call last):
File "", line 1, in
File "", line 3, in demo_no_catch
Exception: general exceptions not caught by specific handling
最佳实践:raise语句raise ValueError('A very specific bad thing happened')
它还方便地允许将任意数量的参数传递给构造函数:raise ValueError('A very specific bad thing happened', 'foo', 'bar', 'baz')
这些参数由异常对象的args属性访问。例如:try:
some_code_that_may_raise_our_value_error()
except ValueError as err:
print(err.args)
印刷品('message', 'foo', 'bar', 'baz')
最佳实践:except子句
例如,在except子句中,您可能希望记录发生了特定类型的错误,然后重新引发。在保留堆栈跟踪的同时,最好的方法是使用一个raise语句。例如:logger = logging.getLogger(__name__)
try:
do_something_in_app_that_breaks_easily()
except AppError as error:
logger.error(error)
raise # just this!
# raise AppError # Don't do this, you'll lose the stack trace!
不要修改你的错误。。。但如果你坚持的话
您可以使用sys.exc_info()来保留stacktrace(和错误值),但这是更容易出错的方式,而且在Python 2和3之间存在兼容性问题,更愿意使用裸raise来重新提升。
为了解释,sys.exc_info()返回类型、值和回溯。type, value, traceback = sys.exc_info()
这是Python2中的语法-注意这与Python3不兼容:raise AppError, error, sys.exc_info()[2] # avoid this.
# Equivalently, as error *is* the second object:
raise sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]
如果您愿意,可以修改新加薪的内容,例如为实例设置新参数:def error():
raise ValueError('oops!')
def catch_error_modify_message():
try:
error()
except ValueError:
error_type, error_instance, traceback = sys.exc_info()
error_instance.args = (error_instance.args[0] + ' ',)
raise error_type, error_instance, traceback
我们在修改args的同时保留了整个回溯。请注意,这不是最佳实践,而且在Python 3中是无效语法(使保持兼容性变得更加困难)。>>> catch_error_modify_message()
Traceback (most recent call last):
File "", line 1, in
File "", line 3, in catch_error_modify_message
File "", line 2, in error
ValueError: oops! raise error.with_traceback(sys.exc_info()[2])
再次:避免手动操作回溯。它是less efficient而且更容易出错。如果你使用线程和sys.exc_info,你甚至可能得到错误的回溯(特别是如果你对控制流使用异常处理,我个人倾向于避免这种情况)
Python 3,异常链接
在Python3中,可以链接异常,以保留跟踪:raise RuntimeError('specific message') from error
注意:此允许更改引发的错误类型,并且
这与Python 2不兼容。
不推荐的方法:
这些代码很容易隐藏,甚至可以进入生产代码。您想要引发异常,执行这些操作将引发异常,但不是预期的异常!raise ValueError, 'message' # Don't do this, it's deprecated!raise 'message' # really really wrong. don't do this.
在所有现代版本中,这实际上会引发TypeError,因为您没有引发BaseException类型。如果您没有检查正确的异常,并且没有知道该问题的审阅者,那么它可能会投入生产。
示例用法
如果用户不正确使用我的API,我会提出异常警告:def api_func(foo):
'''foo should be either 'baz' or 'bar'. returns something very useful.'''
if foo not in _ALLOWED_ARGS:
raise ValueError('{foo} wrong, use "baz" or "bar"'.format(foo=repr(foo)))
创建自己的错误类型"I want to make an error on purpose, so that it would go into the except"
您可以创建自己的错误类型,如果您想指出应用程序中的某些特定错误,只需在异常层次结构中为适当的点创建子类即可:class MyAppLookupError(LookupError):
'''raise this when there's a lookup error for my app'''
使用方法:if important_key not in resource_dict and not ok_to_be_missing:
raise MyAppLookupError('resource is missing, and that is not ok.')