如何在python中加快文件写入速度?
我的任务是用随机数据创建大文件。我开始使用以下代码:如何在python中加快文件写入速度?,python,Python,我的任务是用随机数据创建大文件。我开始使用以下代码: from __future__ import print_function N=10 rand_file = open("file_name", 'w'); for i in range(1, 7000000): print(''.join(random.choice(string.ascii_lowercase) for x in range(N)), file=rand_file)
from __future__ import print_function
N=10
rand_file = open("file_name", 'w');
for i in range(1, 7000000):
print(''.join(random.choice(string.ascii_lowercase)
for x in range(N)),
file=rand_file)
看看这个程序在磁盘上的写入吞吐量,我觉得这不是最快的方法。我想创建一个100MB的连续缓冲区空间,在缓冲区中写入字符串,然后在每次缓冲区填满时将其刷新到文件中。如何在python中实现这一点?我查看了io.BufferedWriter,但不明白如何使用它写入文件
欢迎提出任何建议。谢谢。尝试创建一个大文件,然后写入它应该很快:
import random
N = 2**20
f = open('rand.txt', 'wb')
f.seek(N-1)
f.write('\0')
f.seek(0)
for i in xrange(N-1):
f.write(chr(random.randint(32,127)))
f.close()
值得一提的是,这里有一个使用BufferedWriter的示例:
import io
import random
import string
N=10
rand_file = io.FileIO("file_name", 'w')
writer = io.BufferedWriter(rand_file,buffer_size=100000000)
for i in range(1, 7000000):
writer.write(''.join(random.choice(string.ascii_lowercase) for x in range(N)))
writer.flush()
您可以增加文件的缓冲区大小。默认情况下,它只有8k,并且经常刷新
import random
import time
import string
N = 10
count = 0
start = time.time()
with open('/tmp/xyz','wb',100*(2**20)) as f:
for i in xrange(1,7000000):
s = ''.join(random.choice(string.ascii_lowercase) for x in range(N))
count += len(s)
f.write(s)
delta = time.time() - start
print count/(2**20), 'mb', count/(delta*(2**20)), 'mbs'
这有助于获得大的连续写入,这通常是一件好事,但对性能没有多大帮助。尝试保持random.choice()计算,但不要在代码中打印,这仍然需要很长时间。您是CPU绑定的,而不是IO绑定的。导入
ascii\u lower
和choice
而不是string
和random
减少了执行时间。似乎使用
with
语句打开文件会导致执行时间略微增加
不是写7000行(在我的代码中,我用了这个数字而不是7000000行),最后一个代码的想法是在打印文件中的这个字符串之前,将一些行分组到一个字符串中,它们通过\n
链接到该字符串中。这样,对
print()
的调用次数就会减少
要获得与非行总数除数的分组行数相同的行总数,需要在for循环和xrange中进行一些复杂的计算(最好通过查看代码来取消禁用)
我还选择了一个缓冲区大小,以便它等于将几行分组的字符串中的位数,同时是1024的倍数。文件的每行必须包含10个字符。分组行与
\n
-->链接,共11个字符。最后一个分组行后面没有\n
,但当print()
起作用时,它将添加这样一个字符`\n
因此,对于n分组行,分组字符串中有n*11个字符。作为一个字符==8位,它使n*11*8=n*88。然后找到n很容易:它必须验证n*88=缓冲区大小。我们只需要同时获取1024倍和88倍的缓冲区大小 编辑 看来,试图调整缓冲区的大小并没有带来任何好处,甚至是相反的
from __future__ import print_function
from time import clock
from os.path import getsize
N=10
A,B,C,D,E,F = [],[],[],[],[],[]
repet = 20
total_lines = 7000
结果
1 0.492455605391
2 0.503463149646 102.235 %
3 0.475755717556 96.609 %
4 0.449807168229 91.340 %
5 0.319271024669 64.832 %
6 0.334138277351 67.851 %
11264 % 88 == 0 11264 % 1024 == 0
22528 % 88 == 0 22528 % 1024 == 0
33792 % 88 == 0 33792 % 1024 == 0
45056 % 88 == 0 45056 % 1024 == 0
56320 % 88 == 0 56320 % 1024 == 0
67584 % 88 == 0 67584 % 1024 == 0
78848 % 88 == 0 78848 % 1024 == 0
90112 % 88 == 0 90112 % 1024 == 0
file_name1 84000
file_name2 84000
file_name3 84000
file_name4 84000
file_name5 84000
file_name6 84000
Python不一定是创建包含随机数据的大型文件的最简单或最快的方法。下面的bash代码段将创建一个具有指定长度和随机数据的文件;来源见问题
dd if=/dev/random iflag=fullblock of=$HOME/randomFile bs=1M count=1
这有助于加快写入速度吗?seek将把文件指针向前移动1024个字节,这意味着前1024个字节将被归零。@mc_87:这将分配连续的
N
bytesNo,它不会分配连续的N个字节,它只会创建一个整体,稍后将被填充<代码>休闲和朋友是预分配的答案。您可以运行fallocate
命令,或者。顺便问一下,您使用的是什么操作系统?您现在的速度是多少?您正在使用SSD吗?尝试使用内存中的文件进行比较。我使用的是本地磁盘。这台机器运行在ec2上,我使用的是临时存储,即本地磁盘。我的吞吐量小于1MB/秒。我使用iotop进行了测量。问题可能是print
函数刷新了每一行。尝试使用sys.stdout.write
和显式flush
调用,或使用BufferedWriter
(如答案所示)。您看到我的答案了吗?
import random
from string import ascii_lowercase
for i in xrange(repet):
te = clock()
rand_file3 = open("file_name3", 'w')
for i in range(total_lines):
print(''.join(random.choice(ascii_lowercase)
for x in range(N)),
file=rand_file3)
rand_file3.close()
C.append(clock()-te)
from random import choice
from string import ascii_lowercase
for i in xrange(repet):
te = clock()
rand_file4 = open("file_name4", 'w')
for i in range(total_lines):
print(''.join(choice(ascii_lowercase)
for x in range(N)),
file=rand_file4)
rand_file4.close()
D.append(clock()-te)
from random import choice
from string import ascii_lowercase
buffer_size = 22528
grouped_lines = buffer_size/(11*8)
for i in xrange(repet):
te = clock()
rand_file5 = open("file_name5", 'w') # <== no buffer's size adjusted here
for i in range(0, total_lines, grouped_lines):
u = '\n'.join(''.join(choice(ascii_lowercase)
for x in range(N))
for y in xrange(min(grouped_lines,total_lines-i)))
print(u,file=rand_file5)
rand_file5.close()
E.append(clock()-te)
from random import choice
from string import ascii_lowercase
buffer_size = 22528
grouped_lines = buffer_size/(11*8)
for i in xrange(repet):
te = clock()
rand_file6 = open("file_name6", 'w', buffer_size)
for i in range(0, total_lines, grouped_lines):
u = '\n'.join(''.join(choice(ascii_lowercase)
for x in range(N))
for y in xrange(min(grouped_lines,total_lines-i)))
print(u,file=rand_file6)
rand_file6.close()
F.append(clock()-te)
t1,t2,t3,t4,t5,t6=map(min,(A,B,C,D,E,F))
print ('1 %s\n'
'2 %s %.3f %%\n'
'3 %s %.3f %%\n'
'4 %s %.3f %%\n'
'5 %s %.3f %%\n'
'6 %s %.3f %%\n'
% (t1,
t2,t2/t1*100,
t3,t3/t1*100,
t4,t4/t1*100,
t5,t5/t1*100,
t6,t6/t1*100))
for y in xrange(880,100000,88):
if y%1024==0:
print('%d %% 88 == %d %d %% 1024 == %d'
% (y,y%88,y,y%1024))
print("\nfile_name1",getsize('file_name1'))
for fn in ("file_name2","file_name3",
"file_name4","file_name5",
"file_name6"):
print(fn,getsize(fn))
1 0.492455605391
2 0.503463149646 102.235 %
3 0.475755717556 96.609 %
4 0.449807168229 91.340 %
5 0.319271024669 64.832 %
6 0.334138277351 67.851 %
11264 % 88 == 0 11264 % 1024 == 0
22528 % 88 == 0 22528 % 1024 == 0
33792 % 88 == 0 33792 % 1024 == 0
45056 % 88 == 0 45056 % 1024 == 0
56320 % 88 == 0 56320 % 1024 == 0
67584 % 88 == 0 67584 % 1024 == 0
78848 % 88 == 0 78848 % 1024 == 0
90112 % 88 == 0 90112 % 1024 == 0
file_name1 84000
file_name2 84000
file_name3 84000
file_name4 84000
file_name5 84000
file_name6 84000
dd if=/dev/random iflag=fullblock of=$HOME/randomFile bs=1M count=1