Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/357.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Python编写大型CSV的最快方法_Python_Csv_Numpy - Fatal编程技术网

使用Python编写大型CSV的最快方法

使用Python编写大型CSV的最快方法,python,csv,numpy,Python,Csv,Numpy,我想在csv文件中写入一些随机样本数据,直到它达到1GB大。以下代码正在运行: import numpy as np import uuid import csv import os outfile = 'data.csv' outsize = 1024 # MB with open(outfile, 'ab') as csvfile: wtr = csv.writer(csvfile) while (os.path.getsize(outfile)//1024**2) <

我想在csv文件中写入一些随机样本数据,直到它达到1GB大。以下代码正在运行:

import numpy as np
import uuid
import csv
import os
outfile = 'data.csv'
outsize = 1024 # MB
with open(outfile, 'ab') as csvfile:
    wtr = csv.writer(csvfile)
    while (os.path.getsize(outfile)//1024**2) < outsize:
        wtr.writerow(['%s,%.6f,%.6f,%i' % (uuid.uuid4(), np.random.random()*50, np.random.random()*50, np.random.randint(1000))])    
将numpy导入为np
导入uuid
导入csv
导入操作系统
outfile='data.csv'
超大=1024兆字节
将open(outfile,'ab')作为csvfile:
wtr=csv.writer(csvfile)
而(os.path.getsize(outfile)//1024**2)

如何更快地完成它?

删除所有不必要的内容,因此它应该更快、更容易理解:

import random
import uuid
outfile = 'data.csv'
outsize = 1024 * 1024 * 1024 # 1GB
with open(outfile, 'ab') as csvfile:
    size = 0
    while size < outsize:
        txt = '%s,%.6f,%.6f,%i\n' % (uuid.uuid4(), random.random()*50, random.random()*50, random.randrange(1000))
        size += len(txt)
        csvfile.write(txt)
随机导入
导入uuid
outfile='data.csv'
超大=1024*1024*1024#1GB
将open(outfile,'ab')作为csvfile:
大小=0
当尺寸<超大时:
txt=“%s,%.6f,%.6f,%i\n”“(uuid.uuid4(),random.random()*50,random.random()*50,random.randrange(1000))
大小+=长度(txt)
csvfile.write(txt)

问题似乎主要是IO限制。通过以较大的块写入文件,而不是一次写入一行,可以稍微改善I/O:

import numpy as np
import uuid
import os
outfile = 'data-alt.csv'
outsize = 10 # MB
chunksize = 1000
with open(outfile, 'ab') as csvfile:
    while (os.path.getsize(outfile)//1024**2) < outsize:
        data = [[uuid.uuid4() for i in range(chunksize)],
                np.random.random(chunksize)*50,
                np.random.random(chunksize)*50,
                np.random.randint(1000, size=(chunksize,))]
        csvfile.writelines(['%s,%.6f,%.6f,%i\n' % row for row in zip(*data)])   
这比原始代码快25%



另外,我尝试用所需总行数的估计值替换对
os.path.getsize
的调用。不幸的是,它没有提高速度。由于表示最终整数所需的字节数各不相同,因此估计也不精确——也就是说,它不能完全复制原始代码的行为。因此,我保留了
os.path.getsize

这是对unutbu上述答案的更新:

大部分时间用于生成随机数和检查文件大小

如果提前生成行,则可以评估原始磁盘io性能:

import time
from pathlib import Path
import numpy as np
import uuid
outfile = Path('data-alt.csv')
chunksize = 1_800_000

data = [
    [uuid.uuid4() for i in range(chunksize)],
    np.random.random(chunksize) * 50,
    np.random.random(chunksize) * 50,
    np.random.randint(1000, size=(chunksize,))
]
rows = ['%s,%.6f,%.6f,%i\n' % row for row in zip(*data)]

t0 = time.time()
with open(outfile, 'a') as csvfile:
    csvfile.writelines(rows)
tdelta = time.time() - t0
print(tdelta)

在我的标准860 evo ssd(不是nvme)上,1_800_000行可以获得1.43秒,因此这是1258741行/秒(在我看来不太破旧)

为什么要用numpy标记这个问题,但不要使用它(随机数不需要它)?为什么要创建csv编写器,但每行只写一个字符串?未给出,即在文件未关闭时更新文件大小。自己计算大小,不要使用
getsize
,速度也更快。len(txt)==filesize吗?和
random.randint(1000)
接受2个参数。randint->randrange。而
len(txt)
是一行的长度。OK。但一行的长度或行的长度之和不是文件大小。顺便说一句,你的代码不是更快。试试看。@Balzer82,最快的写入方式可能是购买SSD:)。优化IO中存在瓶颈的代码相当困难。有很多低级别的缓冲和优化正在发生,这是我们看不到的。不要太惊讶应该运行得更快的代码实际上并没有明显更快。
import time
from pathlib import Path
import numpy as np
import uuid
outfile = Path('data-alt.csv')
chunksize = 1_800_000

data = [
    [uuid.uuid4() for i in range(chunksize)],
    np.random.random(chunksize) * 50,
    np.random.random(chunksize) * 50,
    np.random.randint(1000, size=(chunksize,))
]
rows = ['%s,%.6f,%.6f,%i\n' % row for row in zip(*data)]

t0 = time.time()
with open(outfile, 'a') as csvfile:
    csvfile.writelines(rows)
tdelta = time.time() - t0
print(tdelta)