【Python办公】读取Excel太慢?你可能没加这个参数吧!_python读取大文本excel文件太慢
目录
专栏导读
🌸 欢迎来到Python办公自动化专栏—Python处理办公问题,解放您的双手
🏳️🌈 博客主页:请点击——> 一晌小贪欢的博客主页求关注
👍 该系列文章专栏:请点击——>Python办公自动化专栏求订阅
🕷 此外还有爬虫专栏:请点击——>Python爬虫基础专栏求订阅
📕 此外还有python基础专栏:请点击——>Python基础学习专栏求订阅
文章作者技术和水平有限,如果文中出现错误,希望大家能指正🙏
❤️ 欢迎各位佬关注! ❤️
1. 前言
在日常的数据处理工作中,我们经常需要用Python读取Excel文件。但是当文件比较大时,你是否遇到过读取速度慢得让人抓狂的情况?如果你正在使用`openpyxl`库,那么很可能是因为你没有加上一个关键参数:`read_only=True`!
2. 问题场景
想象一下这样的场景:你有一个包含几万行数据的Excel文件,使用常规的方法读取:
import openpyxlimport time# 常规读取方式start_time = time.time()workbook = openpyxl.load_workbook(\'large_data.xlsx\')worksheet = workbook.active# 读取所有数据data = []for row in worksheet.iter_rows(values_only=True): data.append(row)end_time = time.time()print(f\"读取耗时: {end_time - start_time:.2f}秒\")
如果你的文件比较大,这个过程可能需要几十秒甚至几分钟!
神奇的read_only参数
openpyxl
库提供了一个read_only
参数,当设置为True
时,可以显著提升读取性能:
import openpyxlimport time# 使用read_only参数start_time = time.time()workbook = openpyxl.load_workbook(\'large_data.xlsx\', read_only=True)worksheet = workbook.active# 读取所有数据data = []for row in worksheet.iter_rows(values_only=True): data.append(row)end_time = time.time()print(f\"只读模式读取耗时: {end_time - start_time:.2f}秒\")
性能对比测试
让我们通过一个实际的测试来看看性能差异:
import openpyxlimport timeimport pandas as pdfrom openpyxl import Workbookdef create_test_file(filename, rows=10000, cols=10): \"\"\"创建测试用的Excel文件\"\"\" wb = Workbook() ws = wb.active # 写入表头 headers = [f\'Column_{i+1}\' for i in range(cols)] ws.append(headers) # 写入数据 for i in range(rows): row_data = [f\'Data_{i}_{j}\' for j in range(cols)] ws.append(row_data) wb.save(filename) print(f\"测试文件已创建: {filename}\")def test_reading_performance(filename): \"\"\"测试不同读取方式的性能\"\"\" print(\"\\n=== 性能测试开始 ===\") # 方法1: 普通模式 print(\"\\n1. 普通模式读取:\") start_time = time.time() workbook = openpyxl.load_workbook(filename) worksheet = workbook.active data1 = [] for row in worksheet.iter_rows(values_only=True): data1.append(row) normal_time = time.time() - start_time print(f\" 耗时: {normal_time:.2f}秒\") print(f\" 读取行数: {len(data1)}\") workbook.close() # 方法2: 只读模式 print(\"\\n2. 只读模式读取:\") start_time = time.time() workbook = openpyxl.load_workbook(filename, read_only=True) worksheet = workbook.active data2 = [] for row in worksheet.iter_rows(values_only=True): data2.append(row) readonly_time = time.time() - start_time print(f\" 耗时: {readonly_time:.2f}秒\") print(f\" 读取行数: {len(data2)}\") workbook.close() # 方法3: pandas读取(作为对比) print(\"\\n3. pandas读取:\") start_time = time.time() df = pd.read_excel(filename) pandas_time = time.time() - start_time print(f\" 耗时: {pandas_time:.2f}秒\") print(f\" 读取行数: {len(df)}\") # 性能提升计算 improvement = (normal_time - readonly_time) / normal_time * 100 print(f\"\\n=== 性能对比结果 ===\") print(f\"普通模式: {normal_time:.2f}秒\") print(f\"只读模式: {readonly_time:.2f}秒\") print(f\"pandas: {pandas_time:.2f}秒\") print(f\"只读模式比普通模式快 {improvement:.1f}%\")# 运行测试if __name__ == \"__main__\": test_filename = \"performance_test.xlsx\" create_test_file(test_filename, rows=5000, cols=15) test_reading_performance(test_filename)
read_only模式的原理
为什么read_only模式更快?
-
内存优化:
普通模式会将整个工作簿加载到内存中,包括所有的格式信息、公式等。而只读模式只加载必要的数据。
-
跳过格式解析:
只读模式不会解析单元格的格式信息(字体、颜色、边框等),只关注数据内容。
-
流式读取:
只读模式采用流式读取方式,不需要构建完整的对象模型。
限制和注意事项
使用read_only=True
时需要注意以下限制:
import openpyxl# 只读模式的限制示例workbook = openpyxl.load_workbook(\'data.xlsx\', read_only=True)worksheet = workbook.active# ❌ 不能修改数据# worksheet[\'A1\'] = \'New Value\' # 这会报错# ❌ 不能获取格式信息# cell_color = worksheet[\'A1\'].fill # 这会返回默认值# ❌ 不能使用某些方法# worksheet.insert_rows(1) # 这会报错# ✅ 可以读取数据for row in worksheet.iter_rows(values_only=True): print(row)# ✅ 可以访问基本属性print(f\"最大行数: {worksheet.max_row}\")print(f\"最大列数: {worksheet.max_column}\")workbook.close()
实际应用场景
场景1: 数据导入和清洗
import openpyxlfrom datetime import datetimedef import_sales_data(filename): \"\"\"导入销售数据并进行基本清洗\"\"\" workbook = openpyxl.load_workbook(filename, read_only=True) worksheet = workbook.active sales_data = [] headers = None for i, row in enumerate(worksheet.iter_rows(values_only=True)): if i == 0: headers = row continue # 数据清洗 if row[0] is not None: # 确保有订单号 record = { \'order_id\': row[0], \'customer\': row[1], \'amount\': float(row[2]) if row[2] else 0, \'date\': row[3] if isinstance(row[3], datetime) else None } sales_data.append(record) workbook.close() return sales_data# 使用示例sales = import_sales_data(\'sales_report.xlsx\')print(f\"成功导入 {len(sales)} 条销售记录\")
场景2: 大文件数据统计
import openpyxlfrom collections import defaultdictdef analyze_large_dataset(filename): \"\"\"分析大型数据集\"\"\" workbook = openpyxl.load_workbook(filename, read_only=True) worksheet = workbook.active # 统计信息 stats = { \'total_rows\': 0, \'category_count\': defaultdict(int), \'total_amount\': 0, \'max_amount\': 0, \'min_amount\': float(\'inf\') } for i, row in enumerate(worksheet.iter_rows(values_only=True)): if i == 0: # 跳过表头 continue stats[\'total_rows\'] += 1 # 假设第2列是类别,第3列是金额 if len(row) >= 3: category = row[1] amount = row[2] if category: stats[\'category_count\'][category] += 1 if isinstance(amount, (int, float)): stats[\'total_amount\'] += amount stats[\'max_amount\'] = max(stats[\'max_amount\'], amount) stats[\'min_amount\'] = min(stats[\'min_amount\'], amount) workbook.close() return stats# 使用示例result = analyze_large_dataset(\'big_data.xlsx\')print(f\"数据分析结果:\")print(f\"总行数: {result[\'total_rows\']}\")print(f\"总金额: {result[\'total_amount\']:.2f}\")print(f\"最大金额: {result[\'max_amount\']:.2f}\")print(f\"最小金额: {result[\'min_amount\']:.2f}\")
其他性能优化技巧
1. 结合data_only参数
# 如果Excel中有公式,只需要计算结果workbook = openpyxl.load_workbook( \'data.xlsx\', read_only=True, data_only=True # 只读取公式的计算结果)
2. 指定读取范围
# 只读取特定范围的数据workbook = openpyxl.load_workbook(\'data.xlsx\', read_only=True)worksheet = workbook.active# 只读取前1000行data = []for i, row in enumerate(worksheet.iter_rows(values_only=True)): if i >= 1000: break data.append(row)
3. 内存管理
def process_large_file_in_chunks(filename, chunk_size=1000): \"\"\"分块处理大文件\"\"\" workbook = openpyxl.load_workbook(filename, read_only=True) worksheet = workbook.active chunk = [] for i, row in enumerate(worksheet.iter_rows(values_only=True)): chunk.append(row) if len(chunk) >= chunk_size: # 处理当前块 process_chunk(chunk) chunk = [] # 清空块,释放内存 # 处理最后一块 if chunk: process_chunk(chunk) workbook.close()def process_chunk(chunk): \"\"\"处理数据块\"\"\" # 在这里处理数据块 print(f\"处理了 {len(chunk)} 行数据\")
性能对比总结
根据实际测试,使用read_only=True
参数可以带来显著的性能提升:
最佳实践建议
-
只读场景优先使用read_only: 如果你只需要读取数据而不需要修改,总是使用
read_only=True
。 -
结合其他参数: 根据需要结合使用
data_only=True
等参数。 -
适当的数据结构: 对于大量数据,考虑使用生成器或分块处理。
-
及时关闭文件: 使用完毕后及时调用
workbook.close()
释放资源。 -
考虑替代方案: 对于纯数据读取,也可以考虑使用
pandas.read_excel()
或xlrd
库。
# 推荐的读取模式def read_excel_efficiently(filename): \"\"\"高效读取Excel文件的推荐方式\"\"\" try: workbook = openpyxl.load_workbook( filename, read_only=True, data_only=True ) worksheet = workbook.active # 使用生成器节省内存 for row in worksheet.iter_rows(values_only=True): yield row finally: workbook.close()# 使用示例for row_data in read_excel_efficiently(\'large_file.xlsx\'): # 处理每一行数据 process_row(row_data)
结论
如果你在使用Python读取Excel文件时遇到性能问题,不要忘记尝试`read_only=True`参数!这个简单的参数可能会让你的程序快上几倍。当然,在享受性能提升的同时,也要注意只读模式的限制,确保它适合你的使用场景。
记住:性能优化往往就在这些细节之中!
-
希望对初学者有帮助;致力于办公自动化的小小程序员一枚
-
希望能得到大家的【❤️一个免费关注❤️】感谢!
-
求个 🤞 关注 🤞 +❤️ 喜欢 ❤️ +👍 收藏 👍
-
此外还有办公自动化专栏,欢迎大家订阅:Python办公自动化专栏
-
此外还有爬虫专栏,欢迎大家订阅:Python爬虫基础专栏
-
此外还有Python基础专栏,欢迎大家订阅:Python基础学习专栏