【问题标题】:Get data out of a file without iterating through it multiple times从文件中获取数据而无需多次迭代
【发布时间】:2016-07-05 19:47:26
【问题描述】:

我创建了以下函数来从文件中提取数据。它工作正常,但对于较大的文件会变得非常慢。

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 行。

由于我的文件很大,所以我不喜欢我的功能。

  1. 首先是将整个文件读入内存;我这样做是为了可以使用行索引来解析数据。
  2. 其次,文件中的相同行被迭代了很多次——这对于大文件来说非常昂贵。

我一直在尝试使用迭代器一次通过文件,但无法破解它。有什么建议?

【问题讨论】:

  • 只做for line in file 而不是list(file)
  • @cricket_007 谢谢,但如果file 不支持索引,则该函数的其余部分将不起作用。
  • 如果文件不支持索引,那么file[d_line:]怎么样?
  • @cricket_007 行file = list(file) 将其变成list
  • @RickTeachey 我知道list() 会返回什么:)

标签: python function file python-3.x


【解决方案1】:

如果您只想要文件的一小部分,我会使用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))

这不会缓存您已经从文件中读取的行。如果您想这样做,我建议您将所有读取的行存储在字典中,并以行号为键,并且仅在需要时从文件中提取数据。

【讨论】:

  • 看起来islice 是我需要的。仍然需要多次迭代,但这种方式要便宜得多。谢谢。
【解决方案2】:

有点超出左侧字段。但是,如果您可以控制文件,则可以将数据移动到 sqlite3 数据库。

还可以看看 mmap 和 linecache。我想这最后两个只是随机访问文件的包装器。即,您可以通过扫描文件一次,然后构建索引->偏移查找表并使用 seek 来滚动自己。

其中一些方法假设您可以控制正在阅读的文件?

还取决于你是否经常阅读和不经常写作(如果是这样,建立索引并不是一个坏主意)。

【讨论】:

  • 经常阅读和写作几乎从不,但也许时不时。好主意 - 谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-03
  • 2010-09-21
  • 2018-08-25
  • 1970-01-01
相关资源
最近更新 更多