我创建了以下函数来从文件中提取数据。它工作正常,但对于较大的文件来说速度很慢。
def get_data(file, indexes, data_start, sieve_first = is_float):
file_list = list(file)
for i in indexes:
d_line = i+data_start
for line in file_list[d_line:]:
if sieve_first(line.strip().split(',')[0]):
yield file_list[d_line].strip()
d_line += 1
else:
break
def is_float(f):
try:
float(str(f))
except:
return False
else:
return True
with open('my_data') as f:
data = get_data(f, index_list, 3)
该文件可能如下所示(为清晰起见,添加了行号):
line 1234567: # <-- INDEX
line 1234568: # +1
line 1234569: # +2
line 1234570: 8, 17.0, 23, 6487.6
line 1234571: 8, 17.0, 23, 6487.6
line 1234572: 8, 17.0, 23, 6487.6
line 1234572:
line 1234572:
line 1234572:
通过上面的例子,将产生1234570到1234572行。
由于我的文件很大,有些事情我不喜欢我的功能。
我一直在试图使用迭代器来一次性浏览文件,但还是无法破解它。有什么建议?
答案 0 :(得分:2)
如果您只想要文件的一小部分,我会使用itertools.islice。此函数不会存储任何数据,而是存储在内存中的数据。
以下是一个例子:
from itertools import islice
def yield_specific_lines_from_file(filename, start, stop):
with open(filename, 'rb') as ifile:
for line in islice(ifile, start, stop):
yield line
lines = list(yield_specific_lines_from_file('test.txt', 10, 20))
如果您使用Python 3.3或更高版本,您还可以使用yield from
语句简化此操作:
from itertools import islice
def yield_specific_lines_from_file(filename, start, stop):
with open(filename, 'rb') as ifile:
yield from islice(ifile, start, stop)
lines = list(yield_specific_lines_from_file('test.txt', 10, 20))
这不会缓存您已经从文件中读取的行。如果您想这样做,我建议您将所有读取行存储在字典中,并将行号作为键,并且只在需要时从文件中提取数据。
答案 1 :(得分:1)
离开场地了一下。但是,如果您可以控制文件,则可以将数据移动到sqlite3数据库。
另请参阅mmap和linecache。我想这最后两个只是随机访问文件的包装器。也就是说,您可以通过扫描文件一次,然后构建索引 - >偏移查找表并使用搜索来自行滚动。
其中一些方法假设您对您正在阅读的文件有一些控制权?
还取决于你是否经常阅读并且不经常写(如果是这样建立一个索引并不是一个坏主意)。