2015-08-28 19 views
2

我在堆隊列中使用多個生成器來遍歷磁盤上的已排序文件。通常情況下,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處理程序,但它在我的情況好好嘗試一下工作,因爲這個代碼是在長期運行過程中使用。

回答

5

當發電機超出範圍並被刪除時,將調用它們的generator.close() method,這反過來會在發電機功能中產生一個GeneratorExit exception。如果您使用finally:,而不是except GeneratorExit:

def _read_score_index_from_disk(file_name, buffer_size=8*10000): 
    # ... 

    try: 
     # generator loop 
    except GeneratorExit: 
     # clean up after the generator 

那麼塊適用於沒有趕上那些引發的任何異常,當發生自然結束(因爲你不有:

簡單地處理該異常來處理'GeneratorExit')。

+0

對不起,耽誤了!我發現自己再次使用Google搜索,並且很想找到我的問題,並且您的答案我從未標記過。我發現異常和'finally'塊都能工作,但我認爲我更喜歡'finally',因爲它覆蓋了所有的情況。 – Rich

1

您可以在函數外創建一個上下文管理器來處理任何清理任務。

這裏是我的意思一個簡單的例子:

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 
cleaning up