当前位置:
首页 > temp > python入门教程 >
-
Python3 反向按行读取大文件、日志read_reverse_bigfile
适用场景:
反向读取大文件的需求,多半出于想要获取超大的日志文件最后几百行内容,小文件直接通过 lins = file.readlines()[-200:] 就可以直接得出了,
大文件readlines() 会将文件内容全部读取到内存,在GB大小情况下,内存不一定够,列表切片性能差。 生成器反向读取方式更合适。
反向读取大文件,主要依据:
- file对象的seek()函数,偏移文件指针
- re 模块finditer 搜寻文件行尾符,Match对象的end获取行尾符索引位置
- yield 生成器 节省内存
性能验证:
在windows10, RAM 16G,处理器 11th Gen Intel(R) Core(TM) i5-11400 @ 2.60GHz 2.59 GHz , python 3.7.11 下简单验证,
- 读取220M,722万行 文本文件,按行转为列表,read_reverse_bigfile 耗时大概3.8s,内存774MB, file对象readlines()函数,正序读取同样文件耗时大概1.1s,内存552MB。
- 取最后200行内容,read_reverse_bigfile 结果转列表,耗时大概0.8s,占用内存约12MB,file对象readlines()函数 ,列表切片,1.1s,内存约552MB。
import re
def read_reverse_bigfile(filepath, encoding='utf-8', separator=b'\n', single_size=1024 * 1024): """ :param filepath: 文件路径 :param encoding: 字符编码,默认utf-8 :param separator: 行尾分隔符,默认 '\n' :param single_size: 单次读取 字符量,默认 1024*1024 :return: generator """ with open(filepath, 'rb') as f: try: f.seek(0, 2) position = f.tell() if position > single_size: f.seek(-single_size, 2) else: f.seek(0, 0) except OSError as e: return 'Blank file' line = b'' while 1: chunk = f.read(single_size) index_list = [match.end() for match in re.finditer(separator, chunk)] index = None while index_list: target = index_list.pop() if index is None: line = chunk[target:] + line else: line = chunk[target:index] + line if line: yield line.decode(encoding=encoding) line = b'' index = target else: line = chunk[:index] + line position = f.tell() if position > 2 * single_size and single_size > 0: f.seek(-2 * single_size, 1) else: f.seek(0, 0) single_size = position - single_size if single_size <= 0: yield line.decode(encoding=encoding) return 'End'
if __name__ == '__main__': import time import os import psutil pid = os.getpid() p = psutil.Process(pid)
start_time = time.time() fp = r'./test30.txt' rrb = list(read_reverse_bigfile(fp)) print(len(rrb)) print(f'耗时0:{time.time() - start_time}') with open(fp, encoding='utf-8') as f: orl = f.readlines() print(len(orl)) print(f'耗时1:{time.time() - start_time}') info = p.memory_full_info().uss/(1024*1024) print(f'内存信息:{info}MB')
出处:https://www.cnblogs.com/yougnen/p/16081877.html
最新更新
nodejs爬虫
Python正则表达式完全指南
爬取豆瓣Top250图书数据
shp 地图文件批量添加字段
爬虫小试牛刀(爬取学校通知公告)
【python基础】函数-初识函数
【python基础】函数-返回值
HTTP请求:requests模块基础使用必知必会
Python初学者友好丨详解参数传递类型
如何有效管理爬虫流量?
2个场景实例讲解GaussDB(DWS)基表统计信息估
常用的 SQL Server 关键字及其含义
动手分析SQL Server中的事务中使用的锁
openGauss内核分析:SQL by pass & 经典执行
一招教你如何高效批量导入与更新数据
天天写SQL,这些神奇的特性你知道吗?
openGauss内核分析:执行计划生成
[IM002]Navicat ODBC驱动器管理器 未发现数据
初入Sql Server 之 存储过程的简单使用
SQL Server -- 解决存储过程传入参数作为s
关于JS定时器的整理
JS中使用Promise.all控制所有的异步请求都完
js中字符串的方法
import-local执行流程与node模块路径解析流程
检测数据类型的四种方法
js中数组的方法,32种方法
前端操作方法
数据类型
window.localStorage.setItem 和 localStorage.setIte
如何完美解决前端数字计算精度丢失与数