2017-09-20 53 views
0

是否可以使用迭代器從文件中讀取值,以便在迭代結束時自動關閉文件?從文件讀取值的迭代器

使用with語句創建這樣一個迭代器似乎不起作用。

with open('/dev/zero', 'rb') as f:            
    values = iter(f.read(1) for i in (1, 2, 3))         

values.next()    #ValueError: I/O operation on closed file           
+0

您需要創建一個包裝類,實現'__iter__'和'__next__',並在引發'StopIteration'時調用'f .__ exit __()'。 –

+0

你試圖做的事情是不可取的,因爲如果你忘記迭代到最後或發生異常,你會泄漏一個文件句柄。文件上的所有操作都應該在'with'內完成! – MSeifert

回答

2

如果你想使用with你需要做的:

def file_generator(filename): 
    with open(filename,'rb') as file: 
     for i in (1, 2, 3): 
      yield file.read(1) 

values = file_generator('/dev/zero') 
next(values) 

但是,如果你沒有達到這個迭代結束時,你將永遠不會關閉文件,所以它在本質上是不從非常不同:

file = open(filename,'rb') 
next(file) 
file.close() 

當處理一個文件,這是最好的經歷,一次就全部,如果你能,然後將其關閉,一旦你用它做。保持打開文件的句柄通常不是一個可靠的解決方案。

+1

不要在生產代碼中這樣做。當發生器沒有用完時,這可以很容易地泄漏文件句柄,或者如果發生異常,則不會刪除生成器。 (如果在上下文中使用yield,幾乎所有'with'的優點都是否定的)。 – MSeifert

+0

@MSeifert我同意。然而,OP希望在文件上有一個迭代器,所以無論是在兩次調用之間打開文件,還是關閉它,然後每次都重新打開它,但我沒有看到任何令人滿意的解決方案。總而言之,大多數情況下最好一次處理文件,然後關閉它或者實現特殊的自定義使用手柄。 – Flynsee

+0

@MSeifert只要你確定調用'.close()'就應該沒有泄漏,對吧? –

1

fileinput模塊爲你做。打開和關閉文件是自動處理的。

import fileinput 

files = ['path to file'] 

iterator = fileinput.input(files) 

for line in iterator: 
    print(line) 

你可以把多個文件路徑列表的input法就像是在讀取一個文件時,它會遍歷其生產線。

+0

謝謝。我認爲標準的'file'對象已經允許你遍歷行。問題在於何時需要遍歷不是行或不是順序的數據位。 –