![](/img/trans.png)
[英]Reading and parsing HTML files starting from a specific line using Python
[英]Reading CSV files starting from a random line in python
我必須從包含26,00,000行和4列的csv文件(692 MB)中讀取10,000,000行,這些線程在多個線程中,每個線程都從隨機行開始,而當我達到100萬行時停止
我的嘗試:
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']
嚴格要求我每次都要從隨機行開始
這將在沒有多處理的情況下滿足您的要求,部分原因是您很可能不需要它。
一個簡單的基准使選擇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模塊時從任意點開始嘗試解決此問題,也沒有意義。
讓您可以通過做播種開始在字節與點讀從0字節文件的事實f.seek(start_byte)
然后讀取的字節塊在文件中f.read(my_chunk_size)
在這種情況下,要獲得新的一行,您將必須在隨機起始點之后通過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:我對線路緩存有點好奇,因此我也為此提出了一個解決方案。 更新了正確的發電機設置。
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):
具有350萬行,起始行1M,2M,3M並讀取0.5M行的csv。 為了使它與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
=====================================
您是否曾嘗試在運行隨機數生成器之前為其設置種子? 用這樣的代碼:
import time
random.seed(time.time())
在生成任何隨機數之前將其添加
據我了解:
line = linecache.getline('sample.csv', lines_to_get)
這是給您隨機行並將其存儲。
在for循環中,您將立即用csvfile的第一行替換此“行”變量。
for lines_to_get, line in enumerate(csvfile):
print (line)
這導致您丟失先前設置的隨機線。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.