openpyxlでlxmlの有無によるエクセル作成時間の変化を試してみた
lxmlの効果、ありました。
2025.03.28
私たち製造ビジネステクノロジー部では、製造業に関するエンドユーザや事業会社さんに対して、システムやサービスを事業会社さんと一緒に作成・運用しています。そんな製造業において、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 なし
requirements.txt
openpyxl
lxml あり
requirements.txt
openpyxl
lxml
SAMテンプレート
メモリは、2048MBで試します。
template.yaml
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 なし)
app.py
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 あり)
app.py
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 | 












