2017-09-20 52 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'对象已经允许你遍历行。问题在于何时需要遍历不是行或不是顺序的数据位。 –