当前位置: 首页 > 面试题库 >

Python最快访问文件中的行

阎经武
2023-03-14
问题内容

我在文件中有一个ASCII表,我想从中读取一组特定的行(例如,4003至4005行)。问题是该文件可能非常长(例如,十万到几百万行),我想尽快这样做。

错误的解决方案 :读取整个文件,然后转到这些行,

f = open('filename')
lines = f.readlines()[4003:4005]

更好的解决方案enumerate遍历每行,以便不将其全部存储在内存中http://codingdict.com/questions/775

f = open('filename')
lines = []
for i, line in enumerate(f):
    if i >= 4003 and i <= 4005: lines.append(line)
    if i > 4005: break                                    # @Wooble

最佳解决方案?

但这仍然需要遍历每一行。是否有更好的(从速度/效率方面)访问特定线路的方法?即使我只会访问一次文件(通常),也应该使用线缓存吗?

使用二进制文件代替,在这种情况下,跳过可能更容易,这是一个选项—但我宁愿避免使用它。


问题答案:

我可能只会使用itertools.islice。在像文件句柄这样的可迭代对象上使用islice意味着永远不会将整个文件读入内存,并且尽可能快地丢弃前4002行。您甚至可以非常便宜地将所需的两行转换为列表(假设这两行本身不太长)。然后,您可以退出该with块,关闭文件句柄。

from itertools import islice
with open('afile') as f:
    lines = list(islice(f, 4003, 4005))
do_something_with(lines)

更新资料

但是,圣牛的行缓存速度更快,可以进行多次访问。我创建了一个百万行的文件来比较islice和linecache,然后将其删除。

>>> timeit("x=islice(open('afile'), 4003, 4005); print next(x) + next(x)", 'from itertools import islice', number=1)
4003
4004

0.00028586387634277344
>>> timeit("print getline('afile', 4003) + getline('afile', 4004)", 'from linecache import getline', number=1)
4002
4003

2.193450927734375e-05

>>> timeit("getline('afile', 4003) + getline('afile', 4004)", 'from linecache import getline', number=10**5)
0.14125394821166992
>>> timeit("''.join(islice(open('afile'), 4003, 4005))", 'from itertools import islice', number=10**5)
14.732316970825195

不断重新导入和重新读取文件:

这不是一个实际的测试,但是即使在每个步骤中重新导入线缓存,也只比islice慢一秒钟。

>>> timeit("from linecache import getline; getline('afile', 4003) + getline('afile', 4004)", number=10**5)
15.613967180252075

结论

是的,对于所有缓存,linecache的速度都比islice快,但它会不断地重新创建linecache,但是谁来做呢?对于可能的情况(一次仅读取几行,一次读取多行),行缓存速度更快,并且呈现简洁的语法,但是该islice语法也非常干净快捷,并且永远不会将整个文件读入内存。在RAM密集型环境中,islice解决方案可能是正确的选择。对于非常高的速度要求,行缓存可能是更好的选择。但是实际上,在大多数环境中,两次时间都足够小,几乎没有关系。



 类似资料:
  • 问题内容: 搜寻了几个小时后,就开始对此完全取笑。我还在网站上看到了该问题的各种变体,但似乎无法使其正常工作。JFrame需要从ini文件中读取数据,并且我已经创建了一种打开该文件的方法。所述文件存储在jar文件内称为资源的文件夹中。 当我在编译后运行代码时,这当然可以完美地工作,但是在导出到.jar文件后会引发异常。我已经研究过使用InputStream,FileInputStream,但似乎找

  • 问题内容: 我正在优化一些代码,这些代码的主要瓶颈正在运行并访问大量类似于结构的对象。目前,我使用namedtuples来提高可读性。但是使用’timeit’进行的一些快速基准测试表明,在性能是一个重要因素的情况下,这确实是错误的方法: 以a,b,c命名的元组: 使用,a,b,c的类: 带有键a,b,c的字典: 使用常量键的具有三个值的元组: 使用常数键列出三个值: 使用本地键的具有三个值的元组:

  • 问题内容: 我正在Linux系统上使用非常大的文本文件(〜11GB)。我正在通过正在检查文件错误的程序来运行它。一旦发现错误,我需要修复该行或完全删除该行。然后重复… 最终,一旦我对流程感到满意,我便将其完全自动化。但是,现在让我们假设我正在手动运行它。 从此大文件中删除特定行最快(就执行时间而言)是什么?我想到了用Python进行此操作…但是可以接受其他示例。该行可能在文件中的 任何位置 。 如

  • 我目前正在使用此代码访问来自DCIM文件夹的最新图像- 然后获取图像 然后使用光标。moveToNext()以访问下一个图像。 但是,如果我必须以类似的方式访问另一个文件夹(如

  • 我有一个tar存档,其中包含一些其他tar存档。下面的示例完美地提取了primary.tar文件,但我在访问其中的其他.tar文件时遇到了问题。 这将返回以下内容: 所以我可以访问tar1.tar文件对象。但是,我无法弄清楚如何从tar1.tar中获取成员或内容。

  • 问题内容: 我有一个从Matlab 2012b生成的.mat文件。它包含一个带有用户定义的matlab类的变量。 在python 3.3中使用scipy.io.loadmat加载文件时,得到以下信息: 我正在寻找访问类型为“ cStream”的“ futureDS”对象,但似乎无法使用mat [‘None’]进行访问。调用mat [‘None’]简单的结果是: 我被困在这里。我是python的新手