我必须读取csv文件中的10,00,000行(692 MB),包含26,00,000行和4列,包含多个线程,每个行从一个随机行开始,当我达到100万行时停止< / p>
我的尝试:
from multiprocessing.pool import ThreadPool as Pool
import linecache
import random
import csv
from random import randint
from time import sleep
csvfile=csv.reader(open('sample.csv'))
def process_line(l):
sleep(randint(0,3))
print (l)
def get_random_line():
lines_to_get=random.randint(0,2600000)
line = linecache.getline('sample.csv', lines_to_get)
for lines_to_get, line in enumerate(csvfile):
print (line)
if lines_to_get >= 1000000:
break
yield (line)
f = get_random_line()
t = Pool(processes=3)
for i in f:
t.map(process_line, (i,))
t.close()
但是在结果中,线条并非从随机开始,而是每次从第一行开始。
结果
['1', '31', '2.5', '1260759144']
['1', '1029', '3.0', '1260759179']
['1', '1061', '3.0', '1260759182']
['1', '1129', '2.0', '1260759185']
['1', '1172', '4.0', '1260759205']
['1', '1263', '2.0', '1260759151']
['1', '1287', '2.0', '1260759187']
['1', '1293', '2.0', '1260759148']
['1', '1339', '3.5', '1260759125']
严格要求我应该每次从随机行开始
答案 0 :(得分:1)
如果没有多处理,这将完成您的要求,部分原因是您很可能不需要它。
一个简单的基准测试使选项3成为速度的赢家。
选项1:
import csv
import random
starting_points = [random.randint(0, 5) for i in range(3)]
read_nbr_of_lines = 2
for sp in starting_points:
print('random starting line: %s'%sp)
read_lines = 0
with open('large_csv.csv') as cf:
lines = csv.reader(cf)
for nbr, line in enumerate(lines):
if nbr < sp - 1: continue
read_lines += 1
if read_lines > read_nbr_of_lines: break
print(nbr, line)
对于大量数据而言,这可能会变得很慢,但是在使用csv-module时,我希望在随机点开始时尝试解决这个问题。 / p>
通过使用f.seek(start_byte)
对字节上的起始点进行种子设定,然后使用f.read(my_chunk_size)
读取文件中的一大块字节,可以解决从字节0读取文件的问题。在这种情况下,为了获得一个新线,您必须在随机起始点之后通过new_line_char找到自己的行,为行创建自己的解析器并保留一个计数器来读取您读取的行数。
选项2:
如果您的文件小于1GB,这就是您所说的。
在计算机上安装numpy,一次读取文件。
通过索引到整个行集来选择1e6行。
下面将有dtype=np.float64
,如果你想保持整数也有办法做到这一点。为此,我建议研究numpy的文档。
import random
import numpy as np
mycsv = np.genfromtxt('large_csv.csv', delimiter=',')
starting_lines = [random.randint(0, 5) for i in range(3)]
read_nbr_of_lines = 2
for sl in starting_lines:
print('lines %s to %s'%(sl, sl+read_nbr_of_lines-1))
print(mycsv[sl:sl+read_nbr_of_lines])
选项3: 我对linecache有点好奇,所以我也为此做了一个解决方案。 更新了适当的发电机设置。
import linecache as lc
import csv
import random
starting_lines = [random.randint(1, 10) for i in range(3)]
read_nbr_of_lines = 2
for sl in starting_lines:
iterator = (lc.getline('large_csv.csv', i) for
i in range(sl, sl+read_nbr_of_lines))
mycsv = csv.reader(iterator)
print('lines %s to %s'%(sl, sl+read_nbr_of_lines-1))
for row in mycsv:
print(row)
简单基准(Py36):
具有3.5M线的csv,起始线1M,2M,3M和读取0.5M线。为了使它与numpy有些公平,其他人有一行将所有读取行转换为浮动列表。
<强>结果:强>
=====================================
random starting line: 1000000
last_line 1499999 [1.0, 1172.0, 4.0, 1260759205.0]
random starting line: 2000000
last_line 2499999 [1.0, 1263.0, 2.0, 1260759151.0]
random starting line: 3000000
last_line 3499999 [3499999.0, 1287.0, 2.0, 1260759187.0]
option 1 timing: 13.678 seconds
=====================================
random starting line: 1000000
last_line 1499999 [ 1.50000000e+06 1.26300000e+03 2.00000000e+00 1.26075915e+09]
random starting line: 2000000
last_line 2499999 [ 2.50000000e+06 1.28700000e+03 2.00000000e+00 1.26075919e+09]
random starting line: 3000000
last_line 3499999 [ 3.50000000e+06 1.29300000e+03 2.00000000e+00 1.26075915e+09]
option 2 timing: 23.453 seconds
=====================================
lines 1000000 to 1500000
last_line 1500000 [1500000.0, 1263.0, 2.0, 1260759151.0]
lines 2000000 to 2500000
last_line 2500000 [2500000.0, 1287.0, 2.0, 1260759187.0]
lines 3000000 to 3500000
last_line 3500000 [3500000.0, 1293.0, 2.0, 1260759148.0]
option timing: 7.338 seconds
=====================================
答案 1 :(得分:0)
你有没有试过在运行它之前播种你的随机数发生器?用这样的代码:
import time
random.seed(time.time())
在任意随机数生成之前添加
答案 2 :(得分:0)
据我所知:
line = linecache.getline('sample.csv', lines_to_get)
这会让你获得随机行并存储它。
在for循环之后,你立即将这个“line”变量替换为csvfile的第一行。
for lines_to_get, line in enumerate(csvfile):
print (line)
这会导致您丢失先前设置的随机行。