我在堆队列中使用多个生成器来遍历磁盘上的已排序文件。通常,heapq在超出范围之前不会完全耗尽,因此底层生成器永远不会达到StopIteration条件。
我希望能够将处理程序附加到生成器或其他一些优雅的机制,以便在生成器超出范围时删除磁盘上的文件。文件本身是临时的,因此可以删除它们。但是,如果它们没有被删除,程序将最终用临时文件填满磁盘。以下是生成器供参考:
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
处理程序,但它在我的情况下不起作用,因为这个代码将在长时间运行的进程中使用。
答案 0 :(得分:5)
当生成器超出范围并被删除时,会调用generator.close()
method,这会在生成器函数中引发GeneratorExit
exception。
只需处理该异常:
def _read_score_index_from_disk(file_name, buffer_size=8*10000):
# ...
try:
# generator loop
except GeneratorExit:
# clean up after the generator
如果你使用finally:
而不是except GeneratorExit:
,那么该块适用于任何引发的异常,而不会在生成器自然结束时捕获和(因为你没有 来处理`GeneratorExit')。
答案 1 :(得分:1)
您可以从函数中创建一个上下文管理器来处理任何清理任务。
这是我的意思的一个简单例子:
0
1
2
3
4
5
cleaning up
输出:
$sqltopics = "SELECT topic_id, topic_subject, topic_date, topic_cat FROM `forum_topics` WHERE topic_id = ". mysqli_real_escape_string($conn, $_GET['id']) or die(mysqli_error());
$resulttopics = $conn->query($sqltopics);
while($rowtopics = $resulttopics->fetch_array(MYSQLI_ASSOC))
{
$topicname = $rowtopics['topic_subject'];
$topicid = $rowtopics['topic_id'];
}
$sqlposts = "SELECT post_id, post_content, post_date, post_by FROM `forum_posts` WHERE post_topic = ". mysqli_real_escape_string($conn, $_GET['id']) or die(mysqli_error()); ;
$resultposts = $conn->query($sqlposts);
$row_cntposts = $resultposts->num_rows;
<form method="post" action="test.php?id=">
<input type="text" name="reply-content" maxlength="255" size="255" ><br />
<input type="submit" value="Submit reply" />
</form>