python 中的异常传播
Exception propagation in python
我的应用程序使用第三方 API 抛出属于另一个 api 处理模块的异常。代码看起来像这样:
#API Module
def getdatafromapi(req):
# Trying to get data ...
if response_err in data:
raise APIModuleException('API error')
if conn_err in data:
raise APIConnectionError('API error')
# Do some processing
return response
# My Module
def get_data_and_crunch(req):
response = getdatafromapi(req)
if not response:
raise ValueError('Something happened')
# Proceed to number crunch
# Main script
def main():
# Sanitize api request...
try:
get_data_and_crunch(req)
except ValueError:
print('Something happened')
无论 APIModuleException
还是 APIConnectionError
发生,主模块的行为都相同,但我仍然想记录哪个异常 class 实际导致了异常。
有没有一种方法可以避免在我的主脚本中使用 APIModuleException
和 APIConnectionError
classes,并且仍然传播异常,只需使用 ValueError
来判断哪个异常 class 实际上在 API 模块中引起了异常?
不确定我是否理解正确。但这是区分异常的标准方法:
class APIModuleException(Exception): pass
class APIConnectionError(Exception): pass
def get_data_and_crunch(req):
# raise ValueError
raise APIConnectionError
# raise APIModuleException
def main():
# Sanitize api request...
try:
req = None
get_data_and_crunch(req)
except APIModuleException as exc:
# ...handle
print('APIModuleException')
except APIConnectionError as exc:
# ...handle
print('APIConnectionError')
except ValueError as exc:
# ...handle
print('ValueError')
main()
确保您的模块的异常与 API 的异常类型不完全相同。它可以是基本类型,因为 ValueError
似乎是你的情况。你的提升代码在这方面没问题。
添加多个 except
块以捕获不同类型的异常:
try:
get_data_and_crunch()
except (APIModuleException, APIConnectionError) as e:
print('API error caught:', str(e))
except ValueError as e:
print('My module!:', str(e))
您可以拥有任意数量的 except
块,并且每个块都可以捕获任意类型的异常。
如果 API 异常继承自 ValueError
,那么将 ValueError
捕获放在异常之后是非常重要的。这些块按顺序评估,使用 instanceof
,所以如果 ValueError
块先出现,所有异常都会触发它,你永远不会看到 API-specific 消息。
如果您需要了解有关异常的任意特定信息,请使用通过上面显示的 as ...
语法可用的异常对象。函数 sys.exc_info
will also help you get information like the calling sequence that led to the error. You can use the traceback
模块可获取更多详细信息。
更新
根据您的最新评论,您希望在不进行额外导入的情况下获取异常信息。 免责声明:这在技术上是可行的,我将在下面解释一种方法,但我强烈反对这种方法。
诀窍是捕获所有可能出现的异常的基数 class,就像您尝试处理 ValueError
一样。问题是 ValueError
, despite being one of the most widely-used exception types, is not the base of all your exceptions, Exception
is. You could go overboard and catch BaseException
, but then things like pressing Ctrl+C would stop working, so don't do it (just mentioning it for completeness).
您可以使用我在上面向您展示的相同符号来获取类型(以及类型的名称)。回溯也将照常工作,向您展示调用序列和异常发生的位置:
try:
get_data_and_crunch()
except Exception as e:
print('Got a', type(e).__name__)
根据 ,在您深入研究 sys.exc_info
和 traceback
之前,有几种获取基本异常信息的常用方法。 type(e)
将为您提供抛出错误的 class。 str(e)
returns 只是 99% 的正常异常 classes 中的错误消息。 repr(e)
通常会 return 您在打印输出末尾看到的标准 type: message
字符串。
作为我的免责声明的免责声明,我必须补充一点,虽然不推荐使用此类技术,但如果您知道自己在做什么,则可以非常有效地使用它们。因此,请仔细阅读我链接的文档,并确保您彻底理解您的代码。这比注意任何类型的通用不合格警告重要得多。
我的应用程序使用第三方 API 抛出属于另一个 api 处理模块的异常。代码看起来像这样:
#API Module
def getdatafromapi(req):
# Trying to get data ...
if response_err in data:
raise APIModuleException('API error')
if conn_err in data:
raise APIConnectionError('API error')
# Do some processing
return response
# My Module
def get_data_and_crunch(req):
response = getdatafromapi(req)
if not response:
raise ValueError('Something happened')
# Proceed to number crunch
# Main script
def main():
# Sanitize api request...
try:
get_data_and_crunch(req)
except ValueError:
print('Something happened')
无论 APIModuleException
还是 APIConnectionError
发生,主模块的行为都相同,但我仍然想记录哪个异常 class 实际导致了异常。
有没有一种方法可以避免在我的主脚本中使用 APIModuleException
和 APIConnectionError
classes,并且仍然传播异常,只需使用 ValueError
来判断哪个异常 class 实际上在 API 模块中引起了异常?
不确定我是否理解正确。但这是区分异常的标准方法:
class APIModuleException(Exception): pass
class APIConnectionError(Exception): pass
def get_data_and_crunch(req):
# raise ValueError
raise APIConnectionError
# raise APIModuleException
def main():
# Sanitize api request...
try:
req = None
get_data_and_crunch(req)
except APIModuleException as exc:
# ...handle
print('APIModuleException')
except APIConnectionError as exc:
# ...handle
print('APIConnectionError')
except ValueError as exc:
# ...handle
print('ValueError')
main()
确保您的模块的异常与 API 的异常类型不完全相同。它可以是基本类型,因为 ValueError
似乎是你的情况。你的提升代码在这方面没问题。
添加多个 except
块以捕获不同类型的异常:
try:
get_data_and_crunch()
except (APIModuleException, APIConnectionError) as e:
print('API error caught:', str(e))
except ValueError as e:
print('My module!:', str(e))
您可以拥有任意数量的 except
块,并且每个块都可以捕获任意类型的异常。
如果 API 异常继承自 ValueError
,那么将 ValueError
捕获放在异常之后是非常重要的。这些块按顺序评估,使用 instanceof
,所以如果 ValueError
块先出现,所有异常都会触发它,你永远不会看到 API-specific 消息。
如果您需要了解有关异常的任意特定信息,请使用通过上面显示的 as ...
语法可用的异常对象。函数 sys.exc_info
will also help you get information like the calling sequence that led to the error. You can use the traceback
模块可获取更多详细信息。
更新
根据您的最新评论,您希望在不进行额外导入的情况下获取异常信息。 免责声明:这在技术上是可行的,我将在下面解释一种方法,但我强烈反对这种方法。
诀窍是捕获所有可能出现的异常的基数 class,就像您尝试处理 ValueError
一样。问题是 ValueError
, despite being one of the most widely-used exception types, is not the base of all your exceptions, Exception
is. You could go overboard and catch BaseException
, but then things like pressing Ctrl+C would stop working, so don't do it (just mentioning it for completeness).
您可以使用我在上面向您展示的相同符号来获取类型(以及类型的名称)。回溯也将照常工作,向您展示调用序列和异常发生的位置:
try:
get_data_and_crunch()
except Exception as e:
print('Got a', type(e).__name__)
根据 sys.exc_info
和 traceback
之前,有几种获取基本异常信息的常用方法。 type(e)
将为您提供抛出错误的 class。 str(e)
returns 只是 99% 的正常异常 classes 中的错误消息。 repr(e)
通常会 return 您在打印输出末尾看到的标准 type: message
字符串。
作为我的免责声明的免责声明,我必须补充一点,虽然不推荐使用此类技术,但如果您知道自己在做什么,则可以非常有效地使用它们。因此,请仔细阅读我链接的文档,并确保您彻底理解您的代码。这比注意任何类型的通用不合格警告重要得多。