openpyxlライブラリを使ってExcelファイルを読書きしたら、ファイルを開くのに時間がかかり、さらにはファイルを保存するのも時間がかかり、とても使用できないと思いました。それでCSVファイルなら早くなるかと思い、いくつかのライブラリを使って処理時間の測定をしました。ライブラリにより機能が違うので、同一条件で比較することはできないので、あくまでメアスです。
最初にExcelの方がプログラムがわかりやすく書けると考えて、pandas.read_excel/.to_excelを使ったら、起動も保存も遅くて使うものにならず、openpyxl.load_workbook/.saveを使っても遅いので、CSVファイルを使うように方針を変更しました。
pandas.read_excel/.to_excelでも良かったのですが、csv.reader/csv.writerを使いました。GUIアプリの動作結果を1行ずつセルに書き込むので、1行書き込んだら保存するようにしているので、書き込み時間が短いpandasを使った方が良かったかもしれません。GUIアプリを自動操作するので、途中で止まってしまうことがあるので、1行毎に保存しました。
プログラムは、こちらを参照させていただきました。→ Python で Excel ファイルと csv ファイルを読み込む – 解析エンジニアの自動化 blog (hatenablog.com)
測定結果です。(測定日:2021/5/12、xlwingsは2021/5/27)
CSV/Excelファイルは、11,422行です。
ライブラリ | 実行プログラム | CSV/Excel |
読み込み(起動)時間 [sec] |
書き込み時間 [sec] |
|
1 | csv | csv.reader/csv.writer | CSV | 0.12 | 0.80 |
2 |
pandas
|
pd.read_csv/.to_csv
|
CSV
|
0.25 | 0.25 |
3 |
pandas
|
pd.ExcelFile/
|
Excel | 5.43 | – |
4 | pandas | pd.read_excel/.to_excel | Excel | 6.34 | 17.7 |
5 |
dask.dataframe
|
dd.read_csv
|
CSV | 0.05 | – |
6 |
openpyxl
|
op.load_workbook/.save | Excel | 8.34 | 5.87 |
7 |
pywin32
|
xl.Workbooks.Open/.Save | CSV | 1.91 | 0.03 |
8 | pywin32 | xl.Workbooks.Open/.Save | Excel | 0.82 | 0.05 |
9 |
xlwings
|
book_read/book_save
|
Excel | 3.30 | 1.63 |
PCのスペックです。
項目 | 内容 | |
1 | メーカー | 株式会社マウスコンピュータ |
2 | 型番 | MB-W875SN1-SH2-B(17インチのノートPC) |
3 | CPU | Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz |
4 | メモリ | 16.0 GB(8GBx2(PC4-19200 / DDR4-2400) |
5 | SSD | 1TB NVM Express(インテル600p / M.2 PCI Expressx4接続) |
OSです。
1 | エディション | Windows 10 Pro 64ビット |
2 | バージョン | 20H2 |
Pythonとライブラリのバージョンです。
ライブラリ | バージョン | |
1 | Python | 3.8.3 |
2 | csv | 1.0 |
3 | dask | 2.20.0 |
4 | openpyxl | 3.0.4 |
5 | pandas | 1.0.5 |
6 | pywin32 | 取得できなかった |
<考察>
pywin32は、Excelが必要だがVBAと似たように書けるのと、起動は早くはないが、保存が早いので、次はpywin32を使ってみたいと思いました。
あとは、CSVファイルをExcelで開くときにセルによっては、数値の先頭のゼロがなくなったり、日付が勝手に変換されたりしないように開く方法を調べる必要があります。
<ソース>
###############################################################################
# Excelファイルとcsvファイルの読み込みと書き込み時間を計測するプログラム
###############################################################################
# インポート
from time import time
import pandas as pd
import dask.dataframe as dd
import csv
import openpyxl as op
import sys, os
import win32com.client
# 時間計測関数
def calc_time(func):
start = time()
r = func()
return{'value':r, 'time':time()-start}
def csv_reader(ファイル名パス付):
file = open(ファイル名パス付, encoding='cp932')
reader = csv.reader(file)
rows = list(reader)
return reader, rows
def csv_writer(ファイル名パス付, rows):
with open(ファイル名パス付, mode='w', encoding='cp932', newline='') as writeFile:
writer = csv.writer(writeFile)
writer.writerows(rows)
# pywin32
def excel_open(excel_file_name):
#すでにExcelが起動されている場合はそのタスクが使われる
#エラー終了するとタスクは残ります
# xl = win32com.client.Dispatch("Excel.Application")
#動いている様子を見てみる
xl.Visible = True
wb = xl.Workbooks.Open(excel_file_name)
return wb
def excel_save(wb):
wb.Save
# xlwings
def book_read(book_name):
wb = xw.Book(book_name)
return(wb)
def book_save(wb, book_name):
wb.save(book_name)
# def pd_excel_writer(ファイル名パス付, rows):
# # with pd.ExcelWriter(ファイル名パス付, mode='w') as writer:
# # rows.to_excel(writer)
# rows.to_excel(ファイル名パス付)
# 表題行 + 11,421 行のデータ
file_dir = './'
file_name = 'NPO法人情報 - 東京都 - test用'
csv_file_name =file_dir + file_name + '.csv'
excel_file_name =file_dir + file_name + '.xlsx'
csv_file_name_w =file_dir + file_name + '_w.csv'
excel_file_name_w =file_dir + file_name + '_w.xlsx'
# csv(csv_reader / csv_writer)
csv_time = calc_time(lambda:csv_reader(csv_file_name))
print( 'csv_reader で読込にかかった時間 : ' + str(csv_time['time']) + ' sec')
csv_time = calc_time(lambda:csv_writer(csv_file_name_w, csv_time['value']))
print( 'csv_writer で書込にかかった時間 : ' + str(csv_time['time']) + ' sec')
# pandas(pd.read_csv / df.to_csv)
csv_time = calc_time(lambda:pd.read_csv(csv_file_name, encoding='cp932'))
print( 'pd.read_csv で読込にかかった時間 : ' + str(csv_time['time']) + ' sec')
csv_time = calc_time(lambda:csv_time['value'].to_csv(csv_file_name_w, encoding='cp932'))
print( 'df.to_csv で書込にかかった時間 : ' + str(csv_time['time']) + ' sec')
# pandas(pd.ExcelFile)
excel_time = calc_time(lambda:pd.ExcelFile(excel_file_name))
print( 'pd.ExcelFile で読込にかかった時間 : ' + str(excel_time['time']) + ' sec')
# pandas(pd.read_excel / df.to_excel)
excel_time = calc_time(lambda:pd.read_excel(excel_file_name))
print( 'pd.read_excel で読込にかかった時間 : ' + str(excel_time['time']) + ' sec')
excel_time = calc_time(lambda:excel_time['value'].to_excel(excel_file_name_w))
print( 'df.to_excel で書込にかかった時間 : ' + str(excel_time['time']) + ' sec')
# dask.dataframe(dd.read_csv)
csv_time = calc_time(lambda:dd.read_csv(csv_file_name, header=0, encoding='cp932'))
print( 'dd.read_csv で読込にかかった時間 : ' + str(csv_time['time']) + ' sec')
# openpyxl(op.load_workbook / .save)
excel_time = calc_time(lambda:op.load_workbook(excel_file_name))
print( 'op.load_workbook で読込にかかった時間 : ' + str(excel_time['time']) + ' sec')
excel_time = calc_time(lambda:excel_time['value'].save(excel_file_name_w))
print( 'workbook.save で書込にかかった時間 : ' + str(excel_time['time']) + ' sec')
# pywin32(CSV : xl.Workbooks.Open / wb.Save)
xl = win32com.client.Dispatch("Excel.Application")
file_dir = "C:/Users/ujiie/OneDrive/2.Macro/2.usw/1.RPA勉強中/GUI自動操作"
csv_file_name = file_dir + '/' + file_name + '.csv'
csv_time = calc_time(lambda:excel_open(csv_file_name))
wb = csv_time['value']
print( '(CSV)pywin32のexcel_openで読込にかかった時間 : ' + str(csv_time['time']) + ' sec')
csv_time = calc_time(lambda:excel_save(wb))
print( '(CSV)workbook.save で書込にかかった時間 : ' + str(csv_time['time']) + ' sec')
wb.Close(SaveChanges=True)
#他のブックが開いていなければExcelを終了
if xl.Workbooks.Count == 0:
xl.quit()
# pywin32(Excel : xl.Workbooks.Open / wb.Save)
xl = win32com.client.Dispatch("Excel.Application")
file_dir = "C:/Users/ujiie/OneDrive/2.Macro/2.usw/1.RPA勉強中/GUI自動操作"
excel_file_name = file_dir + '/' + file_name + '.xlsx'
excel_time = calc_time(lambda:excel_open(excel_file_name))
wb = excel_time['value']
print( '(Excel)pywin32のexcel_openで読込にかかった時間 : ' + str(excel_time['time']) + ' sec')
excel_time = calc_time(lambda:excel_save(excel_time['value']))
print( '(Excel)workbook.save で書込にかかった時間 : ' + str(excel_time['time']) + ' sec')
wb.Close(SaveChanges=True)
# xlwings
xlwings_time = calc_time(lambda:book_read(excel_file_name))
print( 'book_read で読込にかかった時間 : ' + str(xlwings_time['time']) + ' sec')
xlwings_time = calc_time(lambda:book_save(xlwings_time['value'], excel_file_name_w))
print( 'book_save で書込にかかった時間 : ' + str(xlwings_time['time']) + ' sec')
#他のブックが開いていなければExcelを終了
if xl.Workbooks.Count == 0:
xl.quit()