Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 优雅的机制,以清理发电机,因为它超出了范围?_Python_Generator_File Management - Fatal编程技术网

Python 优雅的机制,以清理发电机,因为它超出了范围?

Python 优雅的机制,以清理发电机,因为它超出了范围?,python,generator,file-management,Python,Generator,File Management,我使用堆队列中的几个生成器来迭代磁盘上的已排序文件。通常情况下,heapq在超出范围之前不会完全耗尽,因此底层生成器永远不会达到停止迭代的条件 我希望能够在生成器超出范围时,将处理程序附加到生成器或其他优雅的机制来删除磁盘上的文件。这些文件本身是临时的,因此可以删除它们。然而,如果它们没有被删除,程序最终会用临时文件填满磁盘。以下是发电机的参考: def _read_score_index_from_disk(file_name, buffer_size=8*10000): """Gen

我使用堆队列中的几个生成器来迭代磁盘上的已排序文件。通常情况下,heapq在超出范围之前不会完全耗尽,因此底层生成器永远不会达到停止迭代的条件

我希望能够在生成器超出范围时,将处理程序附加到生成器或其他优雅的机制来删除磁盘上的文件。这些文件本身是临时的,因此可以删除它们。然而,如果它们没有被删除,程序最终会用临时文件填满磁盘。以下是发电机的参考:

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
,因为它涵盖了所有情况。