我正在编写一个脚本,它读取文件文件夹(每个文件的大小从 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/