Python writelines() 和 write() 巨大的时间差

标签 python performance file file-writing

我正在编写一个脚本,它读取文件文件夹(每个文件的大小从 20 MB 到 100 MB 不等),修改每行中的一些数据,然后写回文件的副本。

with open(inputPath, 'r+') as myRead:
     my_list = myRead.readlines()
     new_my_list = clean_data(my_list)
with open(outPath, 'w+') as myWrite:
     tempT = time.time()
     myWrite.writelines('\n'.join(new_my_list) + '\n')
     print(time.time() - tempT)
print(inputPath, 'Cleaning Complete.')

在使用 90 MB 文件(约 900,000 行)运行此代码时,它会打印 140 秒作为写入文件的时间。这里我使用了 writelines()。所以我搜索了不同的方法来提高文件写入速度,在我阅读的大多数文章中,它说 write()writelines() 应该没有任何区别因为我正在写一个连接的字符串。我还检查了仅以下语句所花费的时间:

new_string = '\n'.join(new_my_list) + '\n'

而且只用了 0.4 秒,所以耗时大不是因为创建列表。 只是为了尝试 write() 我尝试了这段代码:

with open(inputPath, 'r+') as myRead:
     my_list = myRead.readlines()
     new_my_list = clean_data(my_list)
with open(outPath, 'w+') as myWrite:
     tempT = time.time()
     myWrite.write('\n'.join(new_my_list) + '\n')
     print(time.time() - tempT)
print(inputPath, 'Cleaning Complete.')

它打印了 2.5 秒。为什么 write()writelines() 的文件写入时间差异如此之大,即使它们是相同的数据?这是正常行为还是我的代码有问题?两种情况的输出文件似乎都是一样的,所以我知道数据没有丢失。

最佳答案

file.writelines() 需要一个 iterable 字符串。然后它继续循环并为迭代中的每个字符串调用 file.write()。在 Python 中,该方法执行以下操作:

def writelines(self, lines)
    for line in lines:
        self.write(line)

您传入的是一个大字符串,而字符串也是字符串的可迭代对象。迭代时,您会得到 单个字符,长度为 1 的字符串。因此,实际上您是在对 len(data) 单独调用 file.write()。这很慢,因为您一次只构建一个字符的写入缓冲区。

不要将单个字符串传递给 file.writelines()。改为传入列表或元组或其他可迭代对象。

您可以在生成器表达式中添加换行符发送单独的行,例如:

 myWrite.writelines(line + '\n' for line in new_my_list)

现在,如果您可以将 clean_data() 设为 generator,生成已清理的行,您就可以从输入文件流式传输数据,通过数据清理生成器,然后输出到输出文件的内存不超过读写缓冲区所需的内存,但是清理行需要很多状态:

with open(inputPath, 'r+') as myRead, open(outPath, 'w+') as myWrite:
    myWrite.writelines(line + '\n' for line in clean_data(myRead))

此外,我会考虑更新 clean_data() 以发出包含换行符的行。

关于Python writelines() 和 write() 巨大的时间差,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44560655/

相关文章:

python - 即使安装了模块 cv2 也找不到

python - Tshark 不通过 subprocess.Popen 执行

Mysql:从600k行中快速获取50行中的10行(其余由WHERE排除)

c# - 多线程会提高单处理器的计算速度吗

python - lazy=True 在 (Flask-)SQLAlchemy 中

WPF DataGrid 绑定(bind)、调整单元格内大数据(~75k)大小的速度非常慢

Java ByteArray 文件解析

file - centos删除n天前的文件

C# 如何将 File.ReadLines 转换为字符串数组?

python - 如何用 Decimal 创建 Pandas 系列?