0
0

AWS Lambda+PythonでExcelファイルにPlantUMLを埋め込む

Last updated at Posted at 2023-10-07

はじめに

AWS Lambda+PythonでExcelファイルにPlantUMLを埋め込もうとして苦戦したのでメモ

手こずったところ

2023/12/4以降AWS CloudShell環境がAmazon Linux 2からAmazon Linux 2023に更新されていく予定なので、この情報は使えなくなる可能性があります

2024/1/28追記
Amazon Linux 2023のCloudShellでpyenvを使ってPython3.10をインストールする方法
Amazon Linux 2023のCloudShellでは、Python3.9、OpenSSLは3.0.8がデフォルト

# 準備
sudo dnf install gcc zlib-devel bzip2-devel readline-devel sqlite sqlite-devel openssl-devel tk-devel libffi-devel xz-devel

# pyenvインストール
curl https://pyenv.run | bash

# 環境変数設定
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
echo 'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(pyenv init -)"' >> ~/.bashrc

# 環境変数を再読み込み
. .bashrc

# Python3.10.13インストール
pyenv install 3.10.13

# デフォルト指定
pyenv global 3.10.13

準備 - plantwebのレイヤー

AWS CloudShellでPython3.10環境をビルド

AWS CloudShellでPython3.10環境をビルドします。AWS CloudShellのデフォルトでは3.7です。

OpenSSL 1.1.1をインストール

sudo yum install openssl11 openssl11-devel

Python3.10をインストール

sudo yum install gcc bzip2-devel libffi-devel
wget https://www.python.org/ftp/python/3.10.13/Python-3.10.13.tgz
tar xzf Python-3.10.13.tgz
cd Python-3.10.13
./configure --enable-optimizations
sudo make altinstall

(参考)
https://blog.serverworks.co.jp/install-python3-with-openssl11
https://medium.com/@teamcode20233/how-to-upgrade-python-version-in-aws-cloud-shell-bb248ee4c4b2

plantwebのレイヤー作成

確認

python3.10 --version
cd
mkdir python
cd python
python3.10 -m pip install plantweb "urllib3<2" -t .
cd ..
zip -r python python

Lambdaレイヤー

作成したzipファイルをs3に保存します

aws s3 cp python.zip s3://<bucket名>

Lambdaの、レイヤーの作成で、レイヤーを作成します

(参考)
https://qiita.com/__DASHi__/items/268062f0dba0e93170f2

動かしてみる

関数作成

関数作成時にレイヤーを追加します。以下のレイヤーは公開されているものをARNを指定して使用します

  • openpyxl
  • Pillow

サンプルソース

import requests
from plantweb.render import render
import json
import boto3
import openpyxl
from openpyxl.drawing.image import Image
import os
import tempfile
from io import BytesIO

s3_client = boto3.client('s3')

bucket_name = "<bucket名>"
template_name = "template.xlsx"

def lambda_handler(event, context):
    # TODO implement
    object_key = template_name
    s3_resp = s3_client.get_object(Bucket=bucket_name, Key=object_key)
    wb = openpyxl.load_workbook(BytesIO(s3_resp['Body'].read()),data_only=True)
#    main_ws = wb["Sheet1"]

    with tempfile.TemporaryDirectory() as tmpdir:
        file_name = 'output_20231007'
        excel_file_name = f'{file_name}.xlsx'
        tmp_file_path = os.path.join(tmpdir, excel_file_name)

        content = """
        :タイトル;
        """
        output = render(
            content,
            engine = 'plantuml',
            format = 'png',
            cacheopts = {'use_cache': False}
        )
        tmp_png_file_path = os.path.join(tmpdir, 'image.png')
        with open(tmp_png_file_path, 'wb') as f:
            f.write(output[0])
        sheet = wb["Sheet1"]
        img = Image(tmp_png_file_path)
        sheet.add_image(img, "A1")

        wb.save(tmp_file_path)
        wb.close()

        result = s3_client.upload_file(
            Bucket=bucket_name,
            Key=excel_file_name,
            Filename=os.path.join(tmpdir, excel_file_name),
            ExtraArgs={"ContentType": "application/vnd.ms-excel", 'ACL':'public-read'}
        )

    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }

関数URLを有効にして、ブラウザーでURLを表示すると「Hello from Lambda!」と表示されるとともに、S3に出力ファイルが作成されます

こんな感じ

image.png

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0