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 实际导致了异常。

有没有一种方法可以避免在我的主脚本中使用 APIModuleExceptionAPIConnectionError 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_infotraceback 之前,有几种获取基本异常信息的常用方法。 type(e) 将为您提供抛出错误的 class。 str(e) returns 只是 99% 的正常异常 classes 中的错误消息。 repr(e) 通常会 return 您在打印输出末尾看到的标准 type: message 字符串。

作为我的免责声明的免责声明,我必须补充一点,虽然不推荐使用此类技术,但如果您知道自己在做什么,则可以非常有效地使用它们。因此,请仔细阅读我链接的文档,并确保您彻底理解您的代码。这比注意任何类型的通用不合格警告重要得多。