首页 > 解决方案 > Python:关闭资源期间报告错误的最佳实践

问题描述

在 Python 中报告关闭资源时发生的错误的最佳实践是什么?

特别是,如果我实现__enter__and __exit__,我可以使用

with my_library.connect(endpoint) as connection:
   connection.store_data("...")

但是,如果关闭我的连接并保持更改失败,例如由于网络中断,我该怎么办?我知道从技术上讲我可以从内部引发错误,__exit__但这是 Python 中的最佳实践/惯用语吗?或者我应该提供一个单独的persistChanges方法,让__exit__所有错误都被吞下,然后在文档中写“如果你不打电话persistChanges,你可能会在错误情况下丢失你的更改”?

我的具体用例是:我正在向其他开发人员提供 Python API,我想知道如何处理这种“关闭资源时出错”的情况,以便我的 API 遵循 Python 最佳实践/满足使用我的库的 Python 开发人员的期望.

标签: pythoncontextmanager

解决方案


我建议为您的库制作一个自定义错误/警告类。这可以非常非常简单。已经存在一组可以扩展的内置异常。根据您上面的描述,我建议扩展RuntimeError如下:

class MyLibraryConnectionError(RuntimeError):
    pass

或者,如果您只想发出警告,请使用ResourceWarning以下命令:

class MyLibraryConnectionWarning(ResourceWarning):
    pass

还有一个RuntimeWarning可以扩展以获得类似效果。

如果您觉得ResourceWarning, RuntimeWarning, 并且RuntimeError没有准确地描述异常,您也可以让它们直接从Exceptionor继承Warning,这取决于您是否希望它们仅在开发人员模式(警告)下被标记,或者如果您想要完整的异常功能。

您可以像任何其他异常一样抛出这些:

throw MyLibraryConnectionError("The underlying resource failed to close")
throw MyLibraryConnectionWarning("The underlying resource failed to close")

甚至捕获您的依赖项引发的异常:

def __exit__(...):
    try:
        # potentially dangerous code with connections
        underlyingConnection.close()
    except TheErrorYouSeeThrown as e: # you can probably make this Exception instead of TheErrorYouSeeThrown. The more specific the better, so you don't accidentally catch random errors you didn't mean to.
        throw MyLibraryConnectionError(e.message) # or whatever this needs to be, depending on the thrown exception type

然后您的用户可以像这样实现:

try:
    with my_library.connect(endpoint) as connection:
        connection.store_data("...")
except my_library.MyLibraryConnectionError as e:
    # handle appropriately, or ignore
except Exception as e:
    # Handle other errors that happen, that your library doesn't cause.

推荐阅读