openpyxlでlxmlの有無によるエクセル作成時間の変化を試してみた
私たち製造ビジネステクノロジー部では、製造業に関するエンドユーザや事業会社さんに対して、システムやサービスを事業会社さんと一緒に作成・運用しています。そんな製造業において、PLCなどのデータをエクセルにまとめるため、プログラムでエクセルを作る機会がありました。
openpyxlで大量データのあるエクセルを作ると時間が掛かっていたので、公式ドキュメントの内容で改善するかを試してみました。
大量のデータをダンプする場合は、lxmlがインストールされていることを確認してください。
おすすめの方
- AWS Lambdaでopenpyxlとlxmlを利用したい方
- lxmlの有無によるエクセル作成時間の変化を知りたい方
Lambdaをデプロイする
次の4パターンで確認します。
lxml | write-mode |
---|---|
なし | なし |
なし | あり |
あり | なし |
あり | あり |
sam init
sam init \
--runtime python3.11 \
--name lambda-openpyxl-sample \
--app-template hello-world \
--no-tracing \
--no-application-insights \
--structured-logging \
--package-type Zip
requirements.txt
にライブラリを記載する
lxml なし
openpyxl
lxml あり
openpyxl
lxml
SAMテンプレート
メモリは、2048MBで試します。
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: lambda-openpyxl-sample
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
FunctionName: lambda-openpyxl-sample-function
CodeUri: hello_world/
Handler: app.lambda_handler
Runtime: python3.11
MemorySize: 2048
Timeout: 900
Architectures:
- x86_64
HelloWorldFunctionLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub /aws/lambda/${HelloWorldFunction}
Lambdaコード(write-mode なし)
import openpyxl
import time
def lambda_handler(event, context):
wb = openpyxl.Workbook()
ws = wb.active
# 50万行 x 10列のデータを書き込む
begin_write = time.perf_counter()
for i in range(500_000):
ws.append([f"{i}-{j}" for j in range(0, 10)])
end_write = time.perf_counter()
print(f"Write time: {(end_write - begin_write)} s")
begin_save = time.perf_counter()
wb.save("/tmp/hello_world.xlsx")
end_save = time.perf_counter()
print(f"Save time: {end_save - begin_save} s")
if __name__ == "__main__":
lambda_handler(None, None)
Lambdaコード(write-mode あり)
import openpyxl
import time
def lambda_handler(event, context):
wb = openpyxl.Workbook(write_only=True)
ws = wb.create_sheet()
# 50万行 x 10列のデータを書き込む
begin_write = time.perf_counter()
for i in range(500_000):
ws.append([f"{i}-{j}" for j in range(0, 10)])
end_write = time.perf_counter()
print(f"Write time: {(end_write - begin_write)} s")
begin_save = time.perf_counter()
wb.save("/tmp/hello_world.xlsx")
end_save = time.perf_counter()
print(f"Save time: {end_save - begin_save} s")
if __name__ == "__main__":
lambda_handler(None, None)
デプロイ
sam build --use-container
sam deploy
Lambdaを実行してみる
4個のパターンでLambdaを実行します。
aws lambda invoke \
--function-name lambda-openpyxl-sample-function \
output.txt
実行結果
lxmlがあると実行時間が短くなりました。
lxml | write-mode | 行追加[s] | 保存[s] | 全体[s] | メモリ使用量[MB] |
---|---|---|---|---|---|
なし | なし | 23.5 | 69.0 | 92.5 | 1857 |
あり | なし | 23.8 | 49.6 | 73.4 | 1863 |
なし | あり | 74.9 | 4.8 | 79.7 | 356 |
あり | あり | 52.3 | 4.8 | 57.1 | 361 |