【问题标题】:Python readlines faster than readPython readlines 比 read 快
【发布时间】:2018-07-11 08:40:57
【问题描述】:

这与In Python, is read() , or readlines() faster? 相关,但不完全相同。我有一个小文件要多次阅读。我发现用 readlines() 阅读它并加入比用 read() 阅读要快。我找不到很好的解释,但这让我很困惑。

In [34]: cat test.txt
ATOM      1  N   MET A   1      -1.112 -18.674 -30.756  1.00 16.53           N  
ATOM      2  CA  MET A   1       0.327 -18.325 -30.772  1.00 16.53           C  
ATOM      3  C   MET A   1       0.513 -16.897 -31.160  1.00 16.53           C  
ATOM      4  O   MET A   1      -0.063 -15.998 -30.552  1.00 16.53           O  
ATOM      5  CB  MET A   1       1.083 -19.211 -31.777  1.00 16.53           C  
ATOM      6  CG  MET A   1       1.101 -20.691 -31.391  1.00 16.53           C  
ATOM      7  SD  MET A   1       1.989 -21.764 -32.559  1.00 16.53           S  
ATOM      8  CE  MET A   1       3.635 -21.109 -32.159  1.00 16.53           C  
ATOM      9  N   LYS A   2       1.333 -16.657 -32.199  1.00146.35           N  
ATOM     10  CA  LYS A   2       1.595 -15.313 -32.613  1.00146.35           C  

In [35]: timeit open("test.txt").read()
10000 loops, best of 3: 58.7 µs per loop

In [36]: timeit "\n".join(open("test.txt").readlines())
10000 loops, best of 3: 56.4 µs per loop

结果非常一致。

【问题讨论】:

  • 2.3 µs 的差异无关紧要。
  • 为什么不把这个小文件读一遍,然后保存在内存中呢?
  • 它是一个状态文件(在这个例子中它不是)。每次都必须从磁盘读取它,因为它可能被其他进程修改。
  • @LutzHorn 如果您执行一次可能无关紧要,但如果您执行数百万次,这将很重要。对我来说,这只是反直觉。我们想将代码更改为 read() 但我们认为让我们测量一下:D。
  • @guma44 您已经使用 timeit 完成了 10,000 次。您是否打算将此类文件读取数百万次?

标签: python readlines


【解决方案1】:

对于这么小的文件,它没有任何区别。

对于更大的文件...

import timeit

data = '''
ATOM      1  N   MET A   1      -1.112 -18.674 -30.756  1.00 16.53           N  
ATOM      2  CA  MET A   1       0.327 -18.325 -30.772  1.00 16.53           C  
ATOM      3  C   MET A   1       0.513 -16.897 -31.160  1.00 16.53           C  
ATOM      4  O   MET A   1      -0.063 -15.998 -30.552  1.00 16.53           O  
ATOM      5  CB  MET A   1       1.083 -19.211 -31.777  1.00 16.53           C  
ATOM      6  CG  MET A   1       1.101 -20.691 -31.391  1.00 16.53           C  
ATOM      7  SD  MET A   1       1.989 -21.764 -32.559  1.00 16.53           S  
ATOM      8  CE  MET A   1       3.635 -21.109 -32.159  1.00 16.53           C  
ATOM      9  N   LYS A   2       1.333 -16.657 -32.199  1.00146.35           N  
ATOM     10  CA  LYS A   2       1.595 -15.313 -32.613  1.00146.35           C  
'''.lstrip()

names_and_sizes = []

for x in range(1, 10):
    reps = 1 + 2 ** (x + 2)
    with open('test_{}.txt'.format(x), 'w') as outf:
        for x in range(reps):
            outf.write(data)
        names_and_sizes.append((outf.name, outf.tell()))

for filename, size in names_and_sizes:
    a = timeit.timeit(lambda: open(filename).read(), number=1000)
    b = timeit.timeit(lambda: "\n".join(open(filename).readlines()), number=1000)
    print(filename, size, a, b)

输出是

test_1.txt 7290 0.07285173307172954 0.09389211190864444
test_2.txt 13770 0.08125667599961162 0.1290126950480044
test_3.txt 26730 0.08221574104391038 0.17529957089573145
test_4.txt 52650 0.0865904720267281 0.2977212209952995
test_5.txt 104490 0.1046126070432365 0.5687746809562668
test_6.txt 208170 0.1773586180061102 1.1868972890079021
test_7.txt 415530 0.26339677802752703 2.0290830068988726
test_8.txt 830250 0.31897587003186345 4.381448873900808
test_9.txt 1659690 0.6923789769643918 9.483053435920738

或者更直观

(并且两个轴都是对数)

【讨论】:

  • 谢谢,这很直观,但不能解释为什么在小范围内它会变慢。
  • 如果你看一下我的例子中的数字,拆分和连接实际上总是更慢。
  • (仅在 Python 2 上和原始 810 字节文件的拆分和连接速度快 3%。)
  • 这就是我的设置。
  • 您可以在 Github 上分别比较 file.read() 和 file.readlines() 的实现:github.com/python/cpython/blob/2.7/Objects/…github.com/python/cpython/blob/2.7/Objects/…。我想这可能与.read() 必须动态(重新)分配它正在读取的缓冲区这一事实有关,因为它事先不知道要读取的内容的大小。
猜你喜欢
  • 2011-07-01
  • 2022-12-05
  • 1970-01-01
  • 1970-01-01
  • 2019-02-13
  • 1970-01-01
  • 1970-01-01
  • 2011-11-20
  • 1970-01-01
相关资源
最近更新 更多