Python3:读取和处理超大文件

在日常工作中,文件对象是我们常接触到的可迭代类型之一。一般用 for 循环遍历一个文件对象,可以逐行读取它的内容。但这种方式在碰到大文件时,可能会出现一些奇怪的效率问题。

需求:

小明是一位 Python 初学者,在学习了如何用 Python 读取文件后,他想要做一个小练习:计算某个文件中数字字符(0~9)的数量。

场景1:小文件处理

假设现在有一个测试用的小文件 small_file.txt,里面包含了一行行的随机字符串:

feiowe9322nasd9233rl
aoeijfiowejf8322kaf9a
...

代码示例:file_process.py

def count_digits(fname):"""计算文件里包含多少个数字字符"""count = 0with open(fname) as file:for line in file:for s in line:if s.isdigit():count += 1return countfname = "./small_file.txt"
print(count_digits(fname))

运行结果:

# 运行脚本
python3 ./file_process.py# 输出结果
13

场景2:大文件处理

假设现在我们的大文件big_file.txt,大小有5G,且所有的文本都在一行。

大文件 big_file.txt

df2if283rkwefh... <剩余 5 GB 大小> ...

却发现同样的程序花费了一分多钟才给出结果,并且整个执行过程耗光了笔记本电脑的全部 4G 内存。

问题分析:

为什么同一份代码用于大文件时,效率就会变低这么多呢?原因就藏在小明读取文件的方法里。

在代码里所使用的文件读取方式,可谓 Python 里的“标准做法”:首先用 with open (fine_name) 上下文管理器语法获得一个文件对象,然后用 for 循环迭代它,逐行获取文件里的内容。为什么这种文件读取方式会成为标准?这是因为它有两个好处:

(1) with 上下文管理器会自动关闭文件描述符

(2) 在迭代文件对象时,内容是一行一行返回的,不会占用太多内存。

不过这套标准做法虽好,但不是没有缺点。假如被读取的文件里根本就没有任何换行符,那么上面列的第 (2) 个好处就不再成立。缺少换行符以后,程序遍历文件对象时就不知道该何时中断,最终只能一次性生成一个巨大的字符串对象,白白消耗大量时间和内存。这就是 count_digits() 函数在处理 big_file.txt 时变得异常缓慢的原因。

要解决这个问题,我们需要把这种读取文件的“标准做法”暂时放到一边。

解决方法:

使用 while 循环加 read() 方法分块读取。

除了直接遍历文件对象来逐行读取文件内容外,我们还可以调用更底层的 file.read() 方法。与直接用循环迭代文件对象不同,每次调用 file.read(chunk_size), 会马上读取从当前游标位置往后 chunk_size 大小的文件内容,不必等待任何换行符出现。有了 file.read() 方法的帮助,优化后的代码:

def count_digits_v2(fname):"""计算文件里包含多少个数字字符,每次读取 8 KB"""count = 0block_size = 1024 * 8with open(fname) as file:while True:chunk = file.read(block_size)# 当文件没有更多内容时,read 调用将会返回空字符串 ''if not chunk:breakfor s in chunk:if s.isdigit():count += 1return countfname = "./big_file.txt"
print(count_digits_v2(fname))

在新函数中,我们使用了一个 while 循环来读取文件内容,每次最多读 8 KB,程序不再需要在内存中拼接长达数吉字节的字符串,内存占用会大幅降低。

(吉字节是一种数据存储单位,通常用于表示大容量存储设备的容量大小。它等于1024^3(1,073,741,824)字节,或者1,024兆字节。在计算机领域,常用于描述大型文件、程序或数据集的大小,例如硬盘容量、内存容量等。)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/351.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Flask + Bootstrap vs Flask + React/Vue:初学者指南

在这篇博客文章中&#xff0c;我们将比较 Flask Bootstrap 和 Flask React/Vue 这两种技术栈&#xff0c;以帮助初学者了解哪种组合更适合他们的项目需求。我们将从学习曲线、易用性、依赖管理、构建部署和路由定义等方面进行比较。 学习曲线 Flask 是一个基于 Python 的轻…

【Unity】申请D-U-N-S邓氏编码流程

标题 在使用苹果开发者账号的时候&#xff0c;我们需要用到D-U-N-S邓氏编码&#xff0c;那如何申请呢&#xff1f;最近正好帮朋友申请了一个&#xff0c;接下来我来演示一下申请流程。 1.登录苹果开发者账号 登录连接&#xff1a;Apple Developer 没有账号的自己注册一个 2…

安装Git并设置用户信息

安装Git并设置用户信息的过程如下&#xff1a; 安装Git 在Windows系统上&#xff1a; 访问官方Git下载页面&#xff1a;Git - Downloading Package下载适用于Windows系统的安装程序&#xff08;.exe文件&#xff09;。运行安装程序&#xff0c;按照向导进行安装&#xff0c;…

Python-VBA函数之旅-format函数

目录 一、format函数的常见应用场景&#xff1a; 二、format函数的语法结构&#xff1a; 1、format函数&#xff1a; 1-1、Python&#xff1a; 1-2、VBA&#xff1a; 2、推荐阅读&#xff1a; 个人主页&#xff1a;https://blog.csdn.net/ygb_1024?spm1010.2135.…

【OceanBase诊断调优 】—— 建索引执行报错问题排查

背景 建索引可能因各种各样的原因产生报错&#xff0c;本文主要介绍碰到建索引报错时&#xff0c;如何定位到建索引报错的日志&#xff0c;方便后续进一步使用工具一键收集日志/根因分析&#xff0c;分析根本原因。 备注&#xff1a;此文档中涉及的语句适用于版本号>4.2.3…

vivo怎么录屏?玩转手机新体验!(2024最新)

“最近新入手了一款vivo手机&#xff0c;感觉用起来真的很顺手&#xff0c;各种功能都很强大。昨天和朋友一起打游戏&#xff0c;突然想到要记录下精彩瞬间&#xff0c;但是找遍了手机&#xff0c;都没有找到录屏功能。我想请教一下各位vivo手机用户&#xff0c;你们通常在哪里…

深入剖析Tomcat(三) 实现一个简易连接器

Tomcat中的servlet容器叫做Catalina&#xff0c;Catalina有两个主要模块&#xff1a;连接器与容器。在本章&#xff0c;将会建立一个连接器来增强第二章中应用程序的功能&#xff0c;用一种更好的方式来创建request与response对象。 截止文章编写日期&#xff0c;servlet规范已…

ES Master 和data节点分别的职责

目录 Elasticsearch Master 节点 职责 特点 Elasticsearch Data 节点 职责 特点 通俗解释 Elasticsearch Master 节点 职责 集群管理: Master 节点负责整个集群的管理工作&#xff0c;包括集群的配置和控制。元数据管理: 维护集群的状态&#xff0c;包括索引的创建、删…

网络流的C++代码实现与过程讲解

网络流是一种非常重要的图论算法,它在许多实际问题中得到广泛应用。本文将介绍网络流算法的C++代码实现与过程讲解。 算法概述 网络流算法是通过将图中的边看作流量通道,将图的点看作流量的起点或终点,来求解图中的最大或最小流量的问题。它是一种非常重要的最优化算法,广…

DM数据库一次redo日志损坏修复的经历

1 缘由 服务器意外断电了&#xff0c;重新上电后发现DM数据库不能连接&#xff0c;提示网络通信异常&#xff0c;数据库拒绝连接。通过服务查看器发现数据库服务停止&#xff0c;并且手动启动失败&#xff0c;codeexited&#xff0c;status1/failure。 2 问题排查 网上查资料说…

Python教学入门:列表与元组

列表&#xff08;Lists&#xff09;&#xff1a; 定义&#xff1a; 列表是 Python 中最常用的数据类型之一&#xff0c;用于存储一组有序的元素。列表使用方括号 [] 定义&#xff0c;元素之间用逗号 , 分隔。 特点&#xff1a; 列表是可变的&#xff08;Mutable&#xff09;…

WebSocket发送与接收数据

创建websocket对象&#xff0c;参数为服务器websockets地址&#xff1a; websocket new WebSocket("ws:127.0.0.1:7001"); 1、发送文本数据 websocket.send(我太笨了&#xff0c;不知道你说的是啥) 2、发送对象数据 发送对象的话需要通过 JSON.parse() 和JSON.…

Java梳理

梳理 1.ResponseBody return “hello world!” 当需要返回一个值的时候&#xff0c;需要使用到ResponseBody RestControllerControllerResponseBody 1.1没有Controller就不能写 GetMapping("/hello") public String sayHello() { return "Hello, wor…

HQL,SQL刷题,尚硅谷(中级)

目录 相关表结构&#xff1a; 1、order_info表 2、order_detail表 题目及思路解析&#xff1a; 第一题&#xff0c;查询各品类销售商品的种类数及销量最高的商品 第二题 查询用户的累计消费金额及VIP等级 第三题 查询首次下单后第二天连续下单的用户比率 总结归纳&#xff1a…

【双指针】

目录 1. LeetCode 283. 移动零 1.1 题目描述 1.2 题目思路 1.3 实现代码 2. LeetCode 1089. 复写零 2.1 题目描述 2.2 题目思路 2.3 实现代码 3. LeetCode 202. 快乐数 3.1 题目描述 3.2 题目思路 3.3 实现代码 4. LeetCode 11. 盛水最多的容器 4.1 题目描述 …

Debian12 中重新安装MSSQL 并指定服务器、数据库、数据表字段的字符排序规则和默认语言等参数

在 Linux 上配置 SQL Server 设置 - SQL Server | Microsoft Learn 零、查看sql server 服务器支持的字符排序规则 SELECT Name from sys.fn_helpcollations() where name Like Chinese% go------ Chinese_PRC_CI_AI Chinese_PRC_CI_AI_WS Chinese_PRC_CI_AI_KS Chinese_PRC_…

CV 面试指南—深度学习知识点总结(3)

本期专栏文章: CV 面试指南—深度学习知识点总结(1)CV 面试指南—深度学习知识点总结(2)CV 面试指南—深度学习知识点总结(3)CV 面试指南—深度学习知识点总结(4)CV 面试指南—深度学习知识点总结(5)

FPGA中闪灯程序设计示例

在FPGA设计中&#xff0c;闪灯的作用主要是用于测试和验证设计的功能和性能。具体来说&#xff0c;闪灯可以作为一个可视化的指示器&#xff0c;通过控制LED灯的闪烁模式和频率&#xff0c;来显示FPGA的工作状态或调试信息。 例如&#xff0c;在设计过程中&#xff0c;可以编写…

政安晨:【Keras机器学习示例演绎】(二)—— 使用 DeepLabV3+ 进行多类语义分割

目录 简介 下载数据 创建 TensorFlow 数据集 构建 DeepLabV3 模型 训练 利用色图叠加进行推理 对验证图像进行推理 政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: TensorFlow与Keras机器学习实战 希望政安晨的博客能够对您有所裨益…

vue3 emits: [‘update:modelValue‘]

在 Vue.js 中&#xff0c;emits 选项用于声明组件可以触发的事件。[update:modelValue] 是 Vue 3 中用于自定义组件与 v-model 指令配合工作的特殊事件名。 当您使用 v-model 指令与自定义组件进行双向绑定时&#xff0c;Vue 内部实际上是在做以下操作&#xff1a; 将 value …