python3读取文件指定行的三种方案

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

python3读取⽂件指定⾏的三种⽅案
技术背景
考虑到深度学习领域中的数据规模⼀般都⽐较⼤,尤其是训练集,这个限制条件对应到实际编程中就意味着,我们很有可能⽆法将整个数据⽂件的内容全部都加载到内存中。

那么就需要⼀些特殊的处理⽅式,⽐如:创建内存映射⽂件来替代原始⽂件被加载到内存中、预处理数据后再加载内存中以及单次只加载⽂件的⽚段。

其中关于内存映射技术的⼀些应⽤,在前⾯的这2篇和中有所介绍,⽽本⽂将要介绍的是从⽂件中只读取特定⾏的内容的3种解决⽅案。

⾏遍历实现
在python中如果要将⼀个⽂件完全加载到内存中,通过file.readlines()即可,但是在⽂件占⽤较⾼时,我们是⽆法完整的将⽂件加载到内存中的,这时候就需要⽤到python
的file.readline()进⾏迭代式的逐⾏读取:
filename = 'hello.txt'
with open(filename, 'r') as file:
line = file.readline()
counts = 1
while line:
if counts >= 50000000:
break
line = file.readline()
counts += 1
这⾥我们的实现⽅式是先⽤⼀个with语句打开⼀个⽂件,然后⽤readline()函数配合while循环逐⾏加载,最终通过⼀个序号标记来结束循环遍历,输出⽂件第50000000⾏的内容。

该代码的执⾏效果如下:
dechin@ubuntu2004:~/projects/gitlab/dechin/$ time python3 get_line.py
real 0m10.359s
user 0m10.062s
sys 0m0.296s
可以看到这⾥的耗时为10s多⼀些。

linecache实现
虽然在python的readline函数中并没有实现读取指定⾏内容的⽅案,但是在另⼀个库linecache中是实现了的,由于使⽤的⽅式较为简单,这⾥直接放上代码⽰例供参考:filename = 'hello.txt'
import linecache
text = linecache.getline(filename, 50000000)
该代码的执⾏结果如下:
dechin@ubuntu2004:~/projects/gitlab/dechin/$ time python3 get_line.py
real 0m11.904s
user 0m5.672s
sys 0m6.231s
虽然在实现⽅式上简化了许多,但是我们发现这个实现的⽤时超过了11s,还不如我们⾃⼰⼿动实现的循环遍历⽅案。

因此如果是对于性能有⼀定要求的场景,是不建议采⽤这个⽅案的。

命令⾏sed获取
我们知道⽤Linux系统本⾝⾃带的sed指令也是可以获取到⽂件指定⾏或者是指定⾏范围的数据的,其执⾏指令为:sed -n 50000000p filename即表⽰读取⽂件的第50000000⾏的内容。

同时结合python的话,我们可以在python代码中执⾏系统指令并获取输出结果:
filename = 'hello.txt'
import os
result = os.popen('sed -n {}p {}'.format(50000000, filename)).read()
需要注意的是,如果直接运⾏os.system()是没有返回值的,只有os.popen()是有返回值的,并且需要在尾巴加上⼀个read()的选项。

该代码的执⾏结果如下:
dechin@ubuntu2004:~/projects/gitlab/dechin/$ time python3 get_line.py
real 0m2.532s
user 0m0.032s
sys 0m0.020s
可以看到直接使⽤sed指令的执⾏速度很快,但是⽤这种⽅法并不是⼀本万利的,⽐如以下这个例⼦:
filename = 'hello.txt'
import os
result = os.popen('sed -n {}p {}'.format(500, filename)).read()
我们把读取第50000000⾏内容改为读取第500⾏的内容,再运⾏⼀次程序:
dechin@ubuntu2004:~/projects/gitlab/dechin/$ time python3 get_line.py
real 0m2.540s
user 0m0.037s
sys 0m0.013s
然⽽我们发现这个速度并没有因为要读取的⾏数减少了⽽变少,⽽是⼏乎保持不变的。

总结概要
本⽂通过4个测试案例分析了在python中读取⽂件指定⾏内容的⽅案,并得到了⼀些运⾏耗时的数据。

从需求上来说,如果是对于⼩规模的数据,⽐如⼏百⾏规模的数据,建议使⽤readline循环遍历来操作,速度也相当不错,或者是linecache中的函数实现也是可以的,甚⾄可以直接⽤readlines将整个⽂本内容加载到内存中。

但是对于数据规模⽐较⼤的场景,⽐如超过了千万⾏的级别,那么使⽤sed指令的⽅式对指定⾏内容进⾏读取的⽅式,应该是所有⽅式中最快速的。

版权声明
作者ID:DechinPhy。

相关文档
最新文档