首頁 > 軟體

解決使用Pandas 讀取超過65536行的Excel檔案問題

2020-11-10 12:06:05

場景

今天需要合併天貓訂單資料,由於前期6.18活動有很多資料需要處理,將幾個月份合併一起,結果報錯。

問題分析

Excel 檔案的格式曾經發生過一次變化,在 Excel 2007 以前,使用擴充套件名為 .xls 格式的檔案,這種檔案格式是一種特定的二進位制格式,最多支援 65,536 行,256 列表格。從 Excel 2007 版開始,預設採用了基於 XML 的新的檔案格式 .xlsx ,支援的表格行數達到了 1,048,576,列數達到了 16,384。需要注意的是,將 .xlsx 格式的檔案轉換為 .xls 格式的檔案時,65536 行和 256 列之後的資料都會被丟棄。

Pandas 讀取 Excel 檔案的引擎是 xlrd , xlrd 雖然同時支援 .xlsx 和 .xls 兩種檔案格式,但是在原始碼檔案 xlrd/sheet.py 中限制了讀取的 Excel 檔案行數必須小於 65536,列數必須小於 256。

if self.biff_version >= 80:
  self.utter_max_rows = 65536
else:
  self.utter_max_rows = 16384
self.utter_max_cols = 256

這就導致,即使是 .xlsx 格式的檔案, xlrd 依然不支援讀取 65536 行以上的 Excel 檔案(原始碼中還有一個行數限制是 16384,這是因為 Excel 95 時代, xls 檔案所支援的最大行數是 16384)。

解決辦法

openpyxl 是一個專門用來操作 .xlsx 格式檔案的 Python 庫,和 xlrd 相比它對於最大行列數的支援和 .xlsx 檔案所定義的最大行列數一致。

首先安裝 openpyxl :

pip install openpyxl

Pandas 的 read_excel 方法中,有 engine 欄位,可以指定所使用的處理 Excel 檔案的引擎,填入 openpyxl ,再讀取檔案就可以了。

import os
import pandas as pd

# 將檔案讀取出來放一個列表裡面

pwd = '1' # 獲取檔案目錄

# 新建列表,存放檔名
file_list = []

# 新建列表存放每個檔案資料(依次讀取多個相同結構的Excel檔案並建立DataFrame)
dfs = []

for root,dirs,files in os.walk(pwd): # 第一個為起始路徑,第二個為起始路徑下的資料夾,第三個是起始路徑下的檔案。
  for file in files:
    file_path = os.path.join(root, file)
    file_list.append(file_path) # 使用os.path.join(dirpath, name)得到全路徑
    df = pd.read_excel(file_path) # 匯入xlsx檔案,將excel轉換成DataFrame
    dfs.append(df)

# 將多個DataFrame合併為一個
df = pd.concat(dfs)

# 資料輸出,寫入excel檔案,不包含索引資料
# 資料寫入 Excel,需要首先安裝一個 engine,由 engine 負責將資料寫入 Excel,pandas 使用 openpyx 或 xlsxwriter 作為寫入引擎。
df.to_excel('test1.xlsx', index=False,engine='openpyxl') # 匯出 Excel,一般不需要索引,將 index 引數設為 False

補充知識:python使用xlrd讀取excel資料作為requests的請求引數,並把返回的資料寫入excel中

實現功能:

從excel中的第一列資料作為post請求的資料,資料為json格式;把post返回的結果寫入到excel的第二列資料中,並把返回資料與excel中的預期結果做比較,如果與預期一致則在案例執行結果中寫入成功,否則寫入失敗。

每一行的資料都不一樣,可實現迴圈呼叫

# !/usr/bin/env python
# -*- coding:utf-8 -*-
#import xlwt #這個專門用於寫入excel的庫沒有用到
import xlrd
from xlutils.copy import copy
import requests
import json
old_excel = xlrd.open_workbook('excel.xls')
sheet = old_excel.sheets()[0]
url = 'http://10.1.1.32:1380/service/allocFk2'
headers = {'Content-Type': 'application/json'}
i = 0
new_excel = copy(old_excel)
for row in sheet.get_rows():
  data = row[0].value
  response = requests.post(url=url, headers=headers, data=data)
  text = response.text
  #使用json.loads可以把Unicode型別,即json型別轉換成dict型別
  text = json.loads(text)["returnMsg"] #遮蔽這行程式碼即可把返回的完整資料寫入檔案中
  ws = new_excel.get_sheet(0)
  ws.write(i,1,text)
  new_excel.save('excel.xls')
  old_excel = xlrd.open_workbook('excel.xls')
  new_excel = copy(old_excel)
  i = i+1

執行前的excel格式:

傳送報文 返回報文 校驗字元 案例執行結果
{ "projectId" :"0070", "projectAllocBatch" :"1", "serviceCode" :"GT012", "seqNo" :"180800272201GT51286712", "tranTimeStamp" :"20180817102244", "sign" :"2dbb89a6bd86b2af1ff6a76c35c05284" } 交易失敗
{ "projectId" :"0070", "projectAllocBatch" :"1", "serviceCode" :"GT012", "seqNo" :"180800272201GT51286713", "tranTimeStamp" :"20180817102244", "sign" :"2dbb89a6bd86b2af1ff6a76c35c05284" } 交易失敗
{ "projectId" :"0070", "projectAllocBatch" :"1", "serviceCode" :"GT012", "seqNo" :"180800272201GT51286713", "tranTimeStamp" :"20180817102244", "sign" :"2dbb89a6bd86b2af1ff6a76c35c05284" } 交易成功

執行後的結果:

偵錯過程中遇到的問題:

1、一開始在for迴圈的最後沒有增加這兩行程式碼

old_excel = xlrd.open_workbook('excel.xls')

new_excel = copy(old_excel)

這樣的話new_excel永遠都是一開始獲取到的那一個,只會把最後一個迴圈返回的結果寫入檔案,因為之前的全部都被一開始獲取的那個old_excel給覆蓋了,所以每次執行完寫入操作以後都要重新做一次copy操作,這樣就能保證new_excel是最新的。

2、注意執行程式之前要把excel關閉,否則會報錯

以上這篇解決使用Pandas 讀取超過65536行的Excel檔案問題就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援it145.com。


IT145.com E-mail:sddin#qq.com