alf*_*oSR 5 python contextmanager
一些背景
我正在使用一个包,它允许您使用文件中存储的信息来计算有关行星的一些信息(例如它们的速度或位置)。该包包含加载和卸载文件的方法,因此其基本用法如下所示:
load(["File_1", "File_2"])
try:
function()
finally:
unload(["File_1", "File_2"])
Run Code Online (Sandbox Code Playgroud)
由于这是上下文管理器实用程序的教科书示例,并且该包缺少一个,因此我正在编写自己的示例。
class file_manager:
def __init__(self, file_list) -> None:
self.file_list = file_list
load(self.file_list)
return None
def __enter__(self) -> None:
return None
def __exit__(self, exc_type, exc_value, traceback) -> None:
unload(self.file_list)
return None
Run Code Online (Sandbox Code Playgroud)
使用新的上下文管理器,前面的示例可以重写如下:
with file_manager(["File_1", "File_2"]):
function()
Run Code Online (Sandbox Code Playgroud)
该方法保证如果出现错误__exit__,文件仍然会被卸载。function
我的问题
该load函数逐个加载文件,而不首先检查所有文件是否可用。因此,如果File_1存在,但File_2不存在,File_1则会被加载,并且在加载时会引发异常File_2。根据 python 文档:
with 语句保证如果
__enter__()方法返回且没有错误,则__exit__()始终会调用 then。
因此,在前面的情况下,程序的执行将在没有File_2被卸载的情况下结束。
我在寻找什么
我显然可以通过try...except在方法中使用一个子句来解决这个问题__init__():
def __init__(self, file_list) -> None:
self.file_list = file_list
try:
load(self.file_list)
except FileDoesNotExistError:
self.__exit__(FileDoesNotExistError, False, None)
Run Code Online (Sandbox Code Playgroud)
但我想知道这是否是解决这个问题的正确方法。例如,在 Cython 中,类有一个__dealloc__()方法,无论发生什么类型的异常,该方法都保证运行。
您可以使用 包装原始代码contextlib.contextmanager。
from contextlib import contextmanager
@contextmanager
def file_manager(file_list):
try:
load(file_list)
yield None # after this the code inside the with block is executed
finally:
# this is called when the with block has finished
# or when load raises an exception
unload(file_list)
Run Code Online (Sandbox Code Playgroud)
并像这样使用它
with file_manager(["File_1", "File_2"]):
function()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
520 次 |
| 最近记录: |