Python 优雅的机制,以清理发电机,因为它超出了范围?
我使用堆队列中的几个生成器来迭代磁盘上的已排序文件。通常情况下,heapq在超出范围之前不会完全耗尽,因此底层生成器永远不会达到停止迭代的条件 我希望能够在生成器超出范围时,将处理程序附加到生成器或其他优雅的机制来删除磁盘上的文件。这些文件本身是临时的,因此可以删除它们。然而,如果它们没有被删除,程序最终会用临时文件填满磁盘。以下是发电机的参考:Python 优雅的机制,以清理发电机,因为它超出了范围?,python,generator,file-management,Python,Generator,File Management,我使用堆队列中的几个生成器来迭代磁盘上的已排序文件。通常情况下,heapq在超出范围之前不会完全耗尽,因此底层生成器永远不会达到停止迭代的条件 我希望能够在生成器超出范围时,将处理程序附加到生成器或其他优雅的机制来删除磁盘上的文件。这些文件本身是临时的,因此可以删除它们。然而,如果它们没有被删除,程序最终会用临时文件填满磁盘。以下是发电机的参考: def _read_score_index_from_disk(file_name, buffer_size=8*10000): """Gen
def _read_score_index_from_disk(file_name, buffer_size=8*10000):
"""Generator to yield a float/int value from a file, does buffering
and file managment to avoid keeping file open while function is not
invoked"""
file_buffer = ''
file_offset = 0
buffer_offset = 1
while True:
if buffer_offset > len(file_buffer):
data_file = open(file_name, 'rb')
data_file.seek(file_offset)
file_buffer = data_file.read(buffer_size)
data_file.close()
file_offset += buffer_size
buffer_offset = 0
packed_score = file_buffer[buffer_offset:buffer_offset+8]
buffer_offset += 8
if not packed_score:
break
yield struct.unpack('fi', packed_score)
我知道
atexit
处理程序,但它在我的情况下不起作用,因为此代码将用于长时间运行的进程。当生成器超出范围并被删除时,将调用它们,这反过来会在生成器函数中引发一个错误
只需处理该异常:
def _read_score_index_from_disk(file_name, buffer_size=8*10000):
# ...
try:
# generator loop
except GeneratorExit:
# clean up after the generator
如果您使用
finally:
而不是除GeneratorExit:
之外的所有异常,那么当生成器自然结束时(因为您不必处理`GeneratorExit'),块将应用于引发的任何异常。您可以使用函数创建上下文管理器来处理任何清理任务
这里有一个简单的例子来说明我的意思:
from contextlib import contextmanager
def my_generator():
for i in range(10):
if i > 5:
break
yield i
@contextmanager
def generator_context():
yield my_generator()
print("cleaning up")
with generator_context() as generator:
for value in generator:
print(value)
输出:
0
1.
2.
3.
4.
5.
清理
很抱歉耽搁您的时间!我发现自己又在谷歌上搜索了一遍,发现我的问题和你的答案从未被接受过。我发现异常和finally
都可以阻塞,但我更喜欢finally
,因为它涵盖了所有情况。