誰是python上最快的xlsx writer


由於工作需要,需要使用pandas對幾個csv進行篩選,並將篩選結果合並成一個xlsx。

生成的xlsx較大(10-30M)

最開始使用了pandas本身支持的openpyxl和xlsxwriter(those with a .xlsx extension will be written usingxlsxwriter (if available) or openpyxl.

性能都不理想,輸出要等好幾分鍾。

在google上找到了pyExcelerate,號稱是Accelerated Excel XLSX writing library for Python

看了官方提供的benchmark,因為數值較小,當時覺得比起前兩者提高有限,沒有在意。

轉而尋求C++動態庫的方案,找到了libxl。

libxl動態庫是C/C++語言直接操作excel文檔的工具,看主頁的benchmark

High performance

Writing speed is about 2 100 000 cells per second for numbers and 240 000 cells per second for 8-character random strings in binary xls format (CPU 3.2 GHz).

加上C的光環,感覺性能很猛的樣子(現在回頭看,發現人家說的是xls並非xlsx。)

但libxl是需要付費的,$199。

試用的話有讀取行數的限制,會在輸出的excel文件第一行插入

Created by LibXL trial version. Please buy the LibXL full version for removing this message.

因為需要生成的xlsx都在幾十M,打開-刪掉第一行-保存,還是比較不方便的。

遂尋找了好幾個版本的破解版,貌似都不起作用,都有購買信息。。。

期間也被compile的事搞得團團轉

    //網上找一個libxl的python wrapper--“libxlpy”,為了解決在64位win8上完成lib編譯,

    //先后安裝了VSE2008 ,Microsoft Visual C++ Compiler for Python 2.7 , WIN SDK。

    //一直沒能通過,隨后放棄

 

各位爬蟲,麻煩轉載請注明來自博客園好嗎?

http://www.cnblogs.com/lightwind/

 

目光重新回到pyExcelerate上,看到該庫的作者是在Google工作的兩位華人

Authors: Kevin Wang and Kevin Zhang
Copyright 2015 Kevin Wang, Kevin Zhang. Portions copyright Google, Inc.

隨便找了一個文件試了試,感覺應該跟libxl不相上下,隨即冒出了寫一個腳本測試一下三者的性能的想法

開搞!

系統環境:
CPU i5 3337U, RAM 8GB, SSD
Win 8.1 64bit
Python 2.7.9


PyExcelerate 0.6.7
libxl 3.6.2
XlsxWriter 0.7.3

import time,ctypes
import pandas as pd

import pyexcelerate,xlsxwriter

def test_pyexcelerate(fn_prefix,data):
    wb = pyexcelerate.Workbook()
    wb.new_sheet("sheet name", data=data)
    wb.save(fn_prefix+"_pyexcelerate.xlsx")

def test_libxl(fn_prefix,data):
    dll = ctypes.windll.LoadLibrary('bin64_libxl_362.dll')
    book = dll.xlCreateXMLBookCA()
    sheet= dll.xlBookAddSheetA(book, "Sheet10", 0)
    for nrow,rec in enumerate(data, start = 1):     # reserverd the first line for 'Created by LibXL trial version... '
        for ncol,val in enumerate(rec, start = 0):
            #print 'row: %s  , col: %s  %s' % (nrow,ncol,type(val))
            if isinstance(val,float):
                dll.xlSheetWriteNumA(sheet, nrow, ncol, ctypes.c_double(val), 0)
            else:
                dll.xlSheetWriteStrA(sheet, nrow, ncol, ctypes.c_char_p(val), 0)
    dll.xlBookSaveA(book, fn_prefix+"_libxl.xlsx")
    dll.xlBookReleaseA(book)

def test_xlsxwriter(fn_prefix,data):
    workbook = xlsxwriter.Workbook(fn_prefix+"_xlsxwriter.xlsx")
    worksheet = workbook.add_worksheet()
    for nrow,rec in enumerate(data):
        for ncol,val in enumerate(rec):
            worksheet.write(nrow, ncol, val)
    workbook.close()

def bench1():
    for nline in (1000,10000,len(csv_data)):
        fn_prefix=fn[:-4]+'_'+str(nline)
        data = csv_data[:nline]
        print '*** %s lines xlsx benchmark ***' %nline
        for func in (test_pyexcelerate, test_libxl, test_xlsxwriter):
            t1=time.time()
            apply(func,(fn_prefix,data))
            tm=time.time()-t1
            print '%s:  %0.3f' % (func.__name__, tm)
        print ' '

def bench2(func,fn,nline,csv_data):
    fn_prefix=fn[:-4]+'_'+str(nline)
    data = csv_data[:nline]
    print '*** %s lines xlsx benchmark ***' %nline
    t1=time.time()
    apply(func,(fn_prefix,data))
    tm=time.time()-t1
    print '%s:  %0.3f' % (func.__name__, tm)
    print ' '

def test_xlsxwriter_to_excel(df,fn):
    print '*** to_excel xlsx benchmark ***'
    t1=time.time()
    df.to_excel(fn+'.xlsx', sheet_name='Sheet1',index=False)
    tm=time.time()-t1
    print 'pandas to_excel(%s):  %0.3f' %  (pd.get_option('io.excel.xlsx.writer'),tm)

if ( __name__ == "__main__"):
    fn ='EutranCellTdd.csv'
    df = pd.read_csv(fn,encoding='gbk',na_values=["no value"]) #,nrows=1000
    df = df.fillna(0)
    #test_xlsxwriter_to_excel(df,fn)
    csv_data=df.values.tolist()
    #bench1()
    #for monitoring process memory usage.
    func=(test_pyexcelerate, test_libxl, test_xlsxwriter)
    bench2(func[2],fn,len(csv_data),csv_data)

 

測試的樣本是1個有50列97613行的csv文件,其中5列是英文字符串,其余是數值。

測試結果如下:

*** 1000 lines xlsx benchmark ***
test_pyexcelerate:   0.633
test_libxl:          0.531
test_xlsxwriter:     1.456
 
*** 10000 lines xlsx benchmark ***
test_pyexcelerate:   5.974
test_libxl:          5.475
test_xlsxwriter:    13.685

*** 97613 lines xlsx benchmark ***
test_pyexcelerate:  54.461   內存峰值  644M
test_libxl:         51.090   內存峰值 1070M
test_xlsxwriter:   117.300   內存峰值  930M

*** to_excel xlsx benchmark ***
pandas to_excel(xlsxwriter):  239.821  內存峰值922M

結果顯示pyExcelerate與libxl速度差距很小,且內存占優。

由於此前看過的pyExcelerate官方提供的benchmark測試中,pyExcelerate速度差不多是xlsxwriter的2倍,因為最先用pandas的to_excel方法來生成excel文件很慢,所以誤以為pyExcelerate也慢。

所以加入了最后一個測試項,結果說明雖然用的是xlsxwriter引擎,pandas在各個方面總是考慮周到,開銷較大,所以盡量避免使用to_excel方法生成大文件。

總結:推薦使用pyExcelerate

 

pyExcelerate 的文件是最大的,解壓后發現其沒有用SharedStrings,字符串是直接內聯到xml中的,默認作弊,哈哈

XlsxWriter也是可以設置參數來取消SharedStrings,默認是使用SharedStrings

不使用SharedStrings貌似更省內存,但會使最終的生成文件變大。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM