问题描述
项目中需要读取非常大的excel 文件。有几百兆也有可能上2G。使用常规的xlrd 的open_workbook 会一次性把文件load到内存。如果同时出现接个大文件的一个处理就会出现OOM。想要找一种方式分批读取excel 内容,不知道excel是否有支持的相关包?
问题出现的环境背景及自己尝试过哪些方法
尝试 xlrd, pandas 均没有相关的操作。csv倒是简单,但是不符合业务方的需求。
相关代码
// 请把代码文本粘贴到下方(请勿用图片代替代码)
项目中需要读取非常大的excel 文件。有几百兆也有可能上2G。使用常规的xlrd 的open_workbook 会一次性把文件load到内存。如果同时出现接个大文件的一个处理就会出现OOM。想要找一种方式分批读取excel 内容,不知道excel是否有支持的相关包?
尝试 xlrd, pandas 均没有相关的操作。csv倒是简单,但是不符合业务方的需求。
// 请把代码文本粘贴到下方(请勿用图片代替代码)
Hi, 我试了一下。
pd.ExcelFile(file_name)
这一行就已经把excel 整个加载到内存了。
调用前:
now 2019-05-19-22:29:38
内存使用: 0.06
总内存: 16.0
内存占比: 65.5
cpu个数: 8
file_size:66.02 MB
调用后:
now 2019-05-19-22:31:20
内存使用: 0.51
总内存: 16.0
内存占比: 69.6
cpu个数: 8
题主发现的问题如果还是一下子读取,可以尝试根据一楼回答修改下代码就可以做到不全部读取了。
代码中主动指定sheetname,不用pd.ExcelFile读取方式获取sheetname就可以运行以下函数了。
import os
import pandas as pd
HERE = os.path.abspath(os.path.dirname(__file__))
DATA_DIR = os.path.abspath(os.path.join(HERE, '..', 'data'))
def make_df_from_excel(file_name, nrows):
"""Read from an Excel file in chunks and make a single DataFrame.
Parameters
----------
file_name : str
nrows : int
Number of rows to read at a time. These Excel files are too big,
so we can't read all rows in one go.
"""
file_path = os.path.abspath(os.path.join(DATA_DIR, file_name))
# 源代码注释掉以下这一段
#xl = pd.ExcelFile(file_path)
## In this case, there was only a single Worksheet in the Workbook.
#sheetname = xl.sheet_names[0]
# 主动给予sheet名字
sheetname = "sheet1"
# Read the header outside of the loop, so all chunk reads are
# consistent across all loop iterations.
df_header = pd.read_excel(file_path, sheetname=sheetname, nrows=1)
print(f"Excel file: {file_name} (worksheet: {sheetname})")
chunks = []
i_chunk = 0
# The first row is the header. We have already read it, so we skip it.
skiprows = 1
while True:
df_chunk = pd.read_excel(
file_path, sheetname=sheetname,
nrows=nrows, skiprows=skiprows, header=None)
skiprows += nrows
# When there is no data, we know we can break out of the loop.
if not df_chunk.shape[0]:
break
else:
print(f" - chunk {i_chunk} ({df_chunk.shape[0]} rows)")
chunks.append(df_chunk)
i_chunk += 1
df_chunks = pd.concat(chunks)
# Rename the columns to concatenate the chunks with the header.
columns = {i: col for i, col in enumerate(df_header.columns.tolist())}
df_chunks.rename(columns=columns, inplace=True)
df = pd.concat([df_header, df_chunks])
return df
if __name__ == '__main__':
df = make_df_from_excel('claims-2002-2006_0.xls', nrows=10000)
2 回答5.3k 阅读✓ 已解决
2 回答1.2k 阅读✓ 已解决
4 回答1.5k 阅读✓ 已解决
3 回答1.4k 阅读✓ 已解决
3 回答1.3k 阅读✓ 已解决
2 回答961 阅读✓ 已解决
1 回答1.8k 阅读✓ 已解决
Reading large Excel files with Pandas