为什么没有换行符读取文件会更快?

pwa*_*ers 13 python file-io python-3.x

在Python 3.6中,如果有换行符,则读取文件需要更长的时间.如果我有两个文件,一个有换行符,另一个没有换行符(否则它们有相同的文本),那么带换行符的文件大约需要100-200%的时间来读取.我提供了一个具体的例子.

步骤1:创建文件

sizeMB = 128
sizeKB = 1024 * sizeMB

with open(r'C:\temp\bigfile_one_line.txt', 'w') as f:
    for i in range(sizeKB):
        f.write('Hello World!\t'*73)  # There are roughly 73 phrases in one KB

with open(r'C:\temp\bigfile_newlines.txt', 'w') as f:
    for i in range(sizeKB):  
        f.write('Hello World!\n'*73)
Run Code Online (Sandbox Code Playgroud)

步骤#2:使用单行和时间性能读取文件

IPython的

%%timeit
with open(r'C:\temp\bigfile_one_line.txt', 'r') as f:
    text = f.read()
Run Code Online (Sandbox Code Playgroud)

产量

1 loop, best of 3: 368 ms per loop
Run Code Online (Sandbox Code Playgroud)

步骤#3:读取具有许多行和时间性能的文件

IPython的

%%timeit
with open(r'C:\temp\bigfile_newlines.txt', 'r') as f:
    text = f.read()
Run Code Online (Sandbox Code Playgroud)

产量

1 loop, best of 3: 589 ms per loop
Run Code Online (Sandbox Code Playgroud)

这只是一个例子.我已经针对很多不同的情况对它进行了测试,他们做了同样的事情:

  1. 不同的文件大小从1MB到2GB
  2. 使用file.readlines()而不是file.read()
  3. 在单行文件中使用空格而不是制表符('\ t')(即'Hello World!')

我的结论是,带有新行字符('\n')的文件比没有它们的文件需要更长的时间来阅读.但是,我希望所有角色都被视为相同.在读取大量文件时,这会对性能产生重要影响. 有谁知道为什么会这样?

我使用的是Python 3.6.1,Anaconda 4.3.24和Windows 10.

Blc*_*ght 10

当您在文本模式下使用Python打开文件时(默认),它使用它所谓的"通用换行符"(随PEP 278引入,但稍后随着Python 3的发布而有所改变).通用换行符的含义是,无论文件中使用什么类型的换行符,您都只能\n在Python中看到.所以包含的文件foo\nbar看起来与包含foo\r\nbaror 的文件相同foo\rbar(因为\n,\r\n并且\r在某些时候是某些操作系统上使用的所有行结束约定).

提供支持的逻辑可能是导致性能差异的原因.即使\n文件中的字符没有被转换,代码也需要比非换行符更仔细地检查它们.

我怀疑,如果您在二进制模式下打开文件而没有提供此类新行支持,则您看到的性能差异将消失.你也可以在Python 3中传递一个newline参数open,它可以有多种含义,具体取决于你给出的值.我不知道任何特定值会对性能产生什么影响,但如果您看到的性能差异对您的程序很重要,则可能值得测试.我想尝试传球newline=""newline="\n"(或任何平台的常规线路结局).


use*_*ica 5

但是,我希望所有角色都被视为相同.

好吧,他们不是.换行是特别的.

换行符并不总是表示为\n.原因是一个可以追溯到物理电传打印机早期的长篇故事,我不会在这里讨论,但故事结束的地方是Windows使用\r\n,Unix使用\n,以及经典的Mac OS \r.

如果以文本模式打开文件,文件使用的换行符将\n在您阅读时转换为,并\n在您编写时转换为操作系统的换行符约定.在大多数编程语言中,这是由OS级代码动态处理并且相当便宜,但Python以不同的方式做事.

Python有一个名为通用换行符的功能,它试图处理所有换行符约定,无论你使用什么操作系统.即使文件中包含的组合\r,\n\r\n换行符,Python会承认他们都和翻译它们\n.除非您使用newline参数to 配置特定的行结束约定,否则Python 3中默认启用通用换行符open.

在通用换行模式下,文件实现必须以二进制模式读取文件,检查\r\n字符的内容,以及

构造一个新的字符串对象,其中行结尾已翻译

如果它找到\r\r\n行结尾.如果它只找到\n结尾,或者根本找不到行结尾,则不需要执行转换传递或构造新的字符串对象.

构造新字符串和翻译行结尾需要时间.使用选项卡读取文件,Python不必执行转换.