python优化读⽂件⽅案总结
python读⽂件优化⽅案(总结)
python常⽤于作数据分析和机器学习算法⼯具。⽽往往数据量都特别的⼤。从磁盘中⼤量、反复的读取数据也是极其耗时的,如何进⼀步优化这⼀过程极其重要。
下⾯我将就python读取⽂件进⾏优化。
1.实验条件
1.操作系统: window 10
2.⼯具:python
3.6.3
3.数据⼤⼩:113MB
4.数据格式:20000⾏,每⾏1001个浮点数(以英⽂逗号隔开)
5.⽬标:将⽂本中每个浮点数保存到列表lss中
⽅法⼀:readlines()⽅法
这种⽅法是最常⽤、最简单的⽂件读取⽅法。
def method1(path):
file=open(path,'r')
lines =adlines()
lss =[]
for line in lines:
ls = re.split(r',',line)
lss.append(ls)
file.close()
print(len(lss))
优点:将⽂件中所有内容⼀次性的传⼊lines列表中,列表lines每⼀个元素为⽂件中的⼀⾏。
缺点:读取⽂件内容过于庞⼤,将出现内存不⾜或者内存溢出的现象。
时间:1952ms
⽅法⼆:readline()⽅法
这种⽅法是对第⼀种⽅法的优化,每次只将⽂件中的⼀⾏读取到内存中,极⼤的减轻的内存的压⼒。
两者在时间上⽆太明显的差异
def method2(path):
file=open(path,'r')
lss =[]
line = f.readline()
while line:
lss.append(line.split(","))
line = f.readline()
f.close()
时间:1867ms
提⽰:这种⽅法同样也可以采⽤以下⽅法代替:
def method3(path):
f =open(path,'r')
lss =[]
for i in f:
lss.append(i.split(","))
f.close()
该⽅法和readline()的效果相同,python底层⾃动的将指针指向⽂件的开头,遇到\n后截断传到内存中赋值给i,指针⾃动指向下⼀⾏。
⽅法三:linecache库readlines⽅法读取⽂件
linecache库提供readline()和readlines()的⽅法,优点在于将磁盘的⽂件读到缓存中,⼤⼤提⾼了cpu读取速度。
def method4(path):
lines = lines(path)
lss =[]
for line in lines:
ls = line.split(",")
lss.append(ls)
# 清除缓存
linecache.clearcache()
时间:1587ms
⽅法四:mmap库地读取⽂件
mmap是⼀种内存映射⽅法,将磁盘⽂件的地址映射到进程虚拟空间中,cpu对⽤⽂件只需要拿着进程中的⽂件地址去磁盘提取指定⽂件即可。
优点:⽆需将⽂件内容读取到内存或者缓存中,⼤⼤减少了IO流的操作。
def method5(path):
read_lines_count =0
lss =[]
f =open(path,'r')
with contextlib.ap(f.fileno(),0, access=mmap.ACCESS_READ))as m:
m.seek(0,0)
while True:
line = m.readline().strip()
temps = line.split(b',')
lss.append(temps)
read_lines_count +=1
if read_lines_count ==20000:
break
f.close()python怎么读文件
时间:1234ms
⽅法五:多线程+readline()优化
多线程对IO型任务有很⼤的提升。当然过多的线程也将减慢IO的速度。本实现采⽤ 8 线程。具体的线程数可以查看电脑的CPU核⼼数。
def__init__(self,trainFile):
self.file=open(trainFile,'r')
self.lss =[]
def run(self):
with lock:
unt <20000:
line = adline()
self.lss.append(line.split(","))
def print(self):
print(len(self.lss))
if __name__ =="__main__":
a =int(round(time.time()*1000))
train_file ="../测试集(20000).txt"
mT = mThread(train_file)
mts =[]
lock = threading.RLock()
for i in range(8):
t = threading.Thread(target=mT.run,args=())
t.start()
mts.append(t)
for i in mts:
i.join()
mT.print()
b =int(round(time.time()*1000))
print("time:", b - a,'ms')
时间:1498ms
较只是⽤readline⽅法的 单线程速度提升了20%多。
⽅法六:多线程+linecache库readlines⽅法
class mThread_1:
def__init__(self,trainFile):
self.lines = lines(trainFile)
self.lss =[]
def run(self):
with lock:
unt <20000:
line = self.unt]
self.lss.append(line.split(","))
def print(self):
print(len(self.lss))
if __name__ =="__main__":
a =int(round(time.time()*1000))
train_file ="../测试集(20000).txt"
mT = mThread_1(train_file)
mts =[]
lock = threading.RLock()
for i in range(8):
t = threading.Thread(target=mT.run,args=())
t.start()
mts.append(t)
for i in mts:
i.join()
mT.print()
b =int(round(time.time()*1000))
print("time:", b - a,'ms')
速度较单线程linecache提升近20%。
⽅法七:多线程+mmap
class mThread_2:
def__init__(self,trainFile):
self.f =open(trainFile,'r')
self.m = ap(self.f.fileno(),0, access=mmap.ACCESS_READ)
self.lss =[]
def run(self):
with lock:
unt <20000:
line = adline().strip()
temps = line.split(b',')
self.lss.append(temps)
def print(self):
self.f.close()
print(len(self.lss))
if __name__ =="__main__":
a =int(round(time.time()*1000))
train_file ="../测试集(20000).txt"
mT = mThread_2(train_file)
mts =[]
lock = threading.RLock()
for i in range(8):
t = threading.Thread(target=mT.run,args=())
t.start()
mts.append(t)
for i in mts:
i.join()
mT.print()
b =int(round(time.time()*1000))
print("time:", b - a,'ms')
时间:959ms
速度也有20%多的提升。
思考:python下的多线程并⾏计算并不能叫真正的并⾏计算。这受限于GIL(Global Interpreter Lock)限制。每个显线程在执⾏任务时,必须要拿到GIL,这导致在同⼀时间内⼀个进程中不可能有两个及其以上的线程在⼯作。故单CPU的机器在使⽤python进⾏多线程任务时叫单线程的提升不会很
⼤。
但是python中不同进程的GIL是不同的,python可以实现真正的多进程并发。适当的提⾼进程数能很⼤提⾼任务的并发性(过多的进程数超过CPU的核⼼数会导致过剩的进程等待,⽽进程的切换会极⼤的消耗时间)
⽅法⼋:多进程+readlines
def method9(n_pro,each,path):
start = n_pro*each
end =(n_pro +1)*each
file=open(path,'r')
lines =adlines()
ls =[]
for i in range(start,end):
ls.append(lines[i])
file.close()
return ls
if __name__ =="__main__":
a =int(round(time.time()*1000))
train_file ="../测试集(20000).txt"
pro_num =4
tef =open(train_file)
tef.seek(0,2)
read_test_lines_set =ll()/6000/ pro_num)
tef.close()
pool = Pool(processes=pro_num)
lss =[]
for i in range(pro_num):
res = pool.apply_async(method9,(i,read_test_lines_set,train_file)) lss.append(res)
pool.close()
pool.join()
b =int(round(time.time()*1000))
print("time:", b - a,'ms')
时间:1295ms
⽅法九:多进程+linecache
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论