python中大数据文件读取
python中经常会遇到读取大文件的场景。文件较小时,我通常采用下面方法,readlines(),该方法会一次性读取文件的所有行,并将其放入list中,最后存入内存中。可想而知,当文件较大是,内存占用会非常高,甚至造成内存溢出,进程被系统kill掉。
# 读取方式一 with open(file_path, 'r+', encoding='utf-8') as f: count = 0 for line in f.readlines(): count += 1 print(count)
讯享网
运行前:
系统总计内存:8056.3M
系统已经使用内存:6264.3M
系统空闲内存:1791.3M
20465
运行后:
系统总计内存:8056.3M
系统已经使用内存:6266.3M
系统空闲内存:1789.3M
实验采用的文件大小为800k,不算太大,可以看出,占用内存2M。
推荐方法:迭代器迭代遍历
python中有个迭代器的概念。迭代,其实就是对序列中的元素进行处理的一种方式。
下面我们用可迭代对象进行迭代遍历,测试其占用内存大小。for line in f,会自动使用缓存IO以及内存管理。
讯享网# 读取方式二 with open(file_path, 'r+', encoding='utf-8') as f: count = 0 for line in f: count += 1 print(count)
运行前:
系统总计内存:8056.3M
系统已经使用内存:5883.3M
系统空闲内存:2172.3M
20465
运行后:
系统总计内存:8056.3M
系统已经使用内存:5884.3M
系统空闲内存:2171.3M
实验采用的文件大小为800k,不算太大,可以看出,占用内存1M,比第一种方法节约内存。
推荐方法:生成器
生成器(Generator)是创建迭代器的简单而强大的工具。写起来就像是正规的函数,只是在返回数据的时候需要使用yield语句。
# 读取方式三 # 生成器函数,用于自定义创建迭代器read_fileline_generator def read_fileline_generator(file, size=4096): while 1: data = file.read(size) if not data: break yield data with open(file_path, 'r+', encoding='utf-8') as f: count = 0 for line in read_fileline_generator(f): count += 1
运行前:
系统总计内存:8056.3M
系统已经使用内存:5719.3M
系统空闲内存:2336.3M
运行后:
系统总计内存:8056.3M
系统已经使用内存:5720.3M
系统空闲内存:2335.3M
实验采用的文件大小为800k,不算太大,可以看出,占用内存1M,比第一种方法节约内存。
生成器
上面我们采用生成器创建了一个迭代器对文件进行迭代遍历。那什么是生成器呢?我们来仔细研究下生成器,生成器类似于返回值为数组的一个函数。
为了支持迭代协议,拥有yield语句的函数被编译为生成器,这类函数被调用时返回一个生成器对象,返回的对象支持迭代接口,即成员方法__next()__继续从中断处执行执行。
但不同于一般的函数:
一般函数一次性返回所有数值的数组,而生成器函数一次只产生数组中的一个值,这样消耗的内存会大大减少;
一般函数执行完毕后返回值并退出,而生成器函数利用yield关键字,给调用者返回一个值,保留当前执行状态,并自动挂起,便于后面next调用时继续执行。
生成器使用next()函数会比较繁琐,而for循环可以为生成器自动触发next函数。
python中生成器有两种方式:
- 生成器函数:也是用def来定义,利用关键字yield一次返回一个结果,阻塞,重新开始
- 生成器表达式:返回一个对象,这个对象只有在需要的时候才产生结果
上面我们应用了生成器函数,那么生成器表达式是什么呢?
生成器表达式和列表解析类似,但它使用圆括号,而列表解析式用中括号。
讯享网# 列表解析式 list = [ x2 for x in range(5)] print(list) [0, 1, 4, 9, 16] # 生成器表达式 generator_list = (x2 for x in range(5)) print(generator_list) <generator object <genexpr> at 0x0EE83840> print(next(generator_list)) 0 print(next(generator_list)) 1 print(next(generator_list)) 4 print(next(generator_list)) 9 print(next(generator_list)) 16 print(next(generator_list)) Traceback (most recent call last): File "<input>", line 1, in <module> StopIteration
测试代码
# python 读取较大数据文件 import psutil mem = psutil.virtual_memory() print('运行前:') print('系统总计内存:%d.3M' % (float(mem.total)/1024/1024)) print('系统已经使用内存:%d.3M' % (float(mem.used)/1024/1024)) print('系统空闲内存:%d.3M' % (float(mem.free)/1024/1024)) file_path = 'H:\\study\\python\\long.txt' # 读取方式一 # with open(file_path, 'r+', encoding='utf-8') as f: # count = 0 # for line in f.readlines(): # count += 1 # print(count) # 读取方式二 # with open(file_path, 'r+', encoding='utf-8') as f: # count = 0 # for line in f: # count += 1 # print(count) # 读取方式三 def read_fileline_generator(file, size=4096): while 1: data = file.read(size) if not data: break yield data with open(file_path, 'r+', encoding='utf-8') as f: count = 0 for line in read_fileline_generator(f): count += 1 mem2 = psutil.virtual_memory() print('运行后:') print('系统总计内存:%d.3M' % (float(mem2.total) / 1024 / 1024)) print('系统已经使用内存:%d.3M' % (float(mem2.used) / 1024 / 1024)) print('系统空闲内存:%d.3M' % (float(mem2.free) / 1024 / 1024))

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/127480.html