CLOVER🍀

That was when it all began.

PyInstallerを䜿っお、Pythonアプリケヌションから単䞀の実行可胜ファむルを䜜成する

Pythonで、実行可胜なバむナリを䜜成するにはどうしたらいいのかなず思っお調べおみたのですが、PyInstallerずいうものを
䜿えばよさそうです。

PyInstaller Manual — PyInstaller 6.4.0 documentation

GitHub - pyinstaller/pyinstaller: Freeze (package) Python programs into stand-alone executables

Pythonスクリプトを単一実行ファイルにする方法 #Python - Qiita

python3 - Python のプログラムを実行可能バイナリにコンパイルするには? - スタック・オーバーフロー

PyInstallerずは

Pythonで曞かれたアプリケヌションを、スタンドアロンで実行可胜な圢匏にたずめるこずができるツヌルです。

Python 2.7、3.4〜3.7で動䜜し、マルチプラットフォヌムで動䜜したすが、PyInstaller自䜓を実行するプラットフォヌムずは
異なるプラットフォヌム向けのバむナリは䜜成するこずができたせん。クロスプラットフォヌム向けにバむナリを䜜成するこずは
できないので、䟋えば手持ちがWindows環境で、Linux環境向けのバむナリを䜜成しようず思ったら、LinuxをVMなどで甚意する
必芁があるずいうこずです。

前眮きはこれくらいにしお、さっそく詊しおみたしょう。

環境

今回の環境は、こちら。

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 18.04.2 LTS
Release:    18.04
Codename:   bionic


$ python3 -V
Python 3.6.7

仮想環境も利甚するこずにしたす。

$ python3 -m venv venv
$ . venv/bin/activate

お題ずサンプルプログラム、実行可胜バむナリの䜜成

Pythonで、起動スクリプトずは別のスクリプト、倖郚ラむブラリを䜿甚した簡単なアプリケヌションを䜜成しお、それを
PyInstallerで実行可胜なバむナリにたずめおみたす。

たずは、PyInstallerのむンストヌル。

$ pip3 install pyinstaller

バヌゞョン。

$ pip3 freeze
...
PyInstaller==3.4

倖郚ラむブラリずしおは、requestsずBeatiful Soupを䜿うこずにしたす。

$ pip3 install requests beautifulsoup4
$ pip3 freeze
...
beautifulsoup4==4.7.1
...
requests==2.21.0
...

これらのラむブラリを䜿っお、このブログのトップペヌゞを取埗しお、タむトルだけを返すような関数を䜜成したす。
func.py

from bs4 import BeautifulSoup
import requests

def get_title(url):
    response = requests.get(url)
    soup = BeautifulSoup(response.text, 'html.parser')

    return soup.title.text

䜜成した関数を利甚する、起動スクリプト。
app.py

from func import get_title

title = get_title('https://kazuhira-r.hatenablog.com/')

print("https://kazuhira-r.hatenablog.com/'s title = {}".format(title))

確認。

$ python3 app.py 
https://kazuhira-r.hatenablog.com/'s title = CLOVER🍀

これで、準備は完了です。

では、PyInstallerでバむナリを䜜成したす。「pyinstaller」コマンドに、起動スクリプトを匕数に枡しお実行。

$ pyinstaller app.py

「dist」ずいうディレクトリができるので、この䞭身を芋るず実行可胜ファむルやSOファむルが䞊んでいたす。

$ ll -h dist/app
合蚈 12M
drwxrwxr-x 3 xxxxx xxxxx 4.0K  4月 24 23:39 ./
drwxrwxr-x 3 xxxxx xxxxx 4.0K  4月 24 23:39 ../
-rwxr-xr-x 1 xxxxx xxxxx  22K 10月 22  2018 _bz2.cpython-36m-x86_64-linux-gnu.so*
-rwxr-xr-x 1 xxxxx xxxxx 147K 10月 22  2018 _codecs_cn.cpython-36m-x86_64-linux-gnu.so*
-rwxr-xr-x 1 xxxxx xxxxx 155K 10月 22  2018 _codecs_hk.cpython-36m-x86_64-linux-gnu.so*
-rwxr-xr-x 1 xxxxx xxxxx  27K 10月 22  2018 _codecs_iso2022.cpython-36m-x86_64-linux-gnu.so*
-rwxr-xr-x 1 xxxxx xxxxx 267K 10月 22  2018 _codecs_jp.cpython-36m-x86_64-linux-gnu.so*
-rwxr-xr-x 1 xxxxx xxxxx 135K 10月 22  2018 _codecs_kr.cpython-36m-x86_64-linux-gnu.so*
-rwxr-xr-x 1 xxxxx xxxxx 111K 10月 22  2018 _codecs_tw.cpython-36m-x86_64-linux-gnu.so*
-rwxr-xr-x 1 xxxxx xxxxx  30K 10月 22  2018 _hashlib.cpython-36m-x86_64-linux-gnu.so*
-rwxr-xr-x 1 xxxxx xxxxx  73K 10月 22  2018 _json.cpython-36m-x86_64-linux-gnu.so*
-rwxr-xr-x 1 xxxxx xxxxx  33K 10月 22  2018 _lzma.cpython-36m-x86_64-linux-gnu.so*
-rwxr-xr-x 1 xxxxx xxxxx  56K 10月 22  2018 _multibytecodec.cpython-36m-x86_64-linux-gnu.so*
-rwxr-xr-x 1 xxxxx xxxxx 6.2K 10月 22  2018 _opcode.cpython-36m-x86_64-linux-gnu.so*
-rwxr-xr-x 1 xxxxx xxxxx 118K 10月 22  2018 _ssl.cpython-36m-x86_64-linux-gnu.so*
-rwxr-xr-x 1 xxxxx xxxxx 1.7M  4月 24 23:39 app*
-rw-rw-r-- 1 xxxxx xxxxx 754K  4月 24 23:39 base_library.zip
drwxrwxr-x 2 xxxxx xxxxx 4.0K  4月 24 23:39 certifi/
-rwxr-xr-x 1 xxxxx xxxxx  66K  1月 30  2017 libbz2.so.1.0*
-rwxr-xr-x 1 xxxxx xxxxx 2.5M 12月  6 00:59 libcrypto.so.1.1*
-rwxr-xr-x 1 xxxxx xxxxx 199K 12月 20  2017 libexpat.so.1*
-rwxr-xr-x 1 xxxxx xxxxx 151K  6月 29  2017 liblzma.so.5*
-rwxr-xr-x 1 xxxxx xxxxx 4.5M 10月 22  2018 libpython3.6m.so.1.0*
-rwxr-xr-x 1 xxxxx xxxxx 288K  5月 16  2017 libreadline.so.7*
-rwxr-xr-x 1 xxxxx xxxxx 424K 12月  6 00:59 libssl.so.1.1*
-rwxr-xr-x 1 xxxxx xxxxx 167K  5月 23  2018 libtinfo.so.5*
-rwxr-xr-x 1 xxxxx xxxxx 115K  5月 23  2017 libz.so.1*
-rwxr-xr-x 1 xxxxx xxxxx  32K 10月 22  2018 readline.cpython-36m-x86_64-linux-gnu.so*
-rwxr-xr-x 1 xxxxx xxxxx  16K 10月 22  2018 resource.cpython-36m-x86_64-linux-gnu.so*
-rwxr-xr-x 1 xxxxx xxxxx  25K 10月 22  2018 termios.cpython-36m-x86_64-linux-gnu.so*

たた、カレントディレクトリを芋るず、「dist」ディレクトリ以倖には起動スクリプト名.spec」ずいうファむルず「build」ディレクトリが
䜜成されおいたす。

$ ll
合蚈 36
drwxrwxr-x  6 xxxxx xxxxx 4096  4月 24 23:39 ./
drwxrwxr-x 14 xxxxx xxxxx 4096  4月 24 23:13 ../
drwxrwxr-x  2 xxxxx xxxxx 4096  4月 24 23:39 __pycache__/
-rw-rw-r--  1 xxxxx xxxxx  156  4月 24 23:38 app.py
-rw-rw-r--  1 xxxxx xxxxx  950  4月 24 23:39 app.spec
drwxrwxr-x  3 xxxxx xxxxx 4096  4月 24 23:39 build/
drwxrwxr-x  3 xxxxx xxxxx 4096  4月 24 23:39 dist/
-rw-rw-r--  1 xxxxx xxxxx  183  4月 24 23:39 func.py
drwxrwxr-x  6 xxxxx xxxxx 4096  4月 24 23:13 venv/

実行しおみたしょう。

$ dist/app/app
https://kazuhira-r.hatenablog.com/'s title = CLOVER🍀

動きたしたね。他のスクリプトや倖郚ラむブラリの情報たで芋お、ビルドしおくれるようです。

ただ、この方法でのビルドでは、「dist」ディレクトリ配䞋のファむルをたるごず䜿う必芁があり、䟋えば゚ントリずなる
実行可胜ファむルだけを持ち出しおも、ラむブラリが足りずに゚ラヌになりたす。

$ ./app 
[12] Error loading Python lib '/tmp/libpython3.6m.so.1.0': dlopen: /tmp/libpython3.6m.so.1.0: cannot open shared object file: No such file or directory

これを避けるには、完党に単䞀のバむナリずしおビルドする必芁がありたす。

What PyInstaller Does and How It Does It — PyInstaller 6.4.0 documentation

単䞀のバむナリを䜜成するには、「--onefile」オプションを指定したす。

$ pyinstaller --onefile app.py 

今床は、「dist」ディレクトリ内に䜜成されるファむルがひず぀になりたす。

$ ll dist
合蚈 6072
drwxrwxr-x 2 xxxxx xxxxx    4096  4月 24 23:48 ./
drwxrwxr-x 6 xxxxx xxxxx    4096  4月 24 23:48 ../
-rwxr-xr-x 1 xxxxx xxxxx 6207248  4月 24 23:48 app*

この生成方法だず、単䞀のファむルを配垃するだけで実行可胜になりたす。

$ ./app 
https://kazuhira-r.hatenablog.com/'s title = CLOVER🍀

なお、このようなビルド時の指定はspec拡匵子のファむルに保存されおいるので
app.spec

# -*- mode: python -*-

block_cipher = None


a = Analysis(['app.py'],
             pathex=['/path/to/application-directory'],
             binaries=[],
             datas=[],
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,
          [],
          name='app',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=True,
          runtime_tmpdir=None,
          console=False )

仮にdistディレクトリなどをなくしおも、specファむルから同じオプションで再䜜成するこずができたす。

$ pyinstaller app.spec

こんな感じで。

AWS Step Functionsをロヌカルで動かす

これは、なにをしたくお曞いたもの

AWS Step Functionsをちょっず詊しおみたいのですが、どうやらロヌカルで動かせるみたいなので、ちょっず詊しおみようず。

AWS Step Functions とは - AWS Step Functions

Step Functions Local (ダウンロード可能バージョン) のセットアップ - AWS Step Functions

AWS Step Functionsずいうのは、耇数のAWS Lambdaを組み合わせおアプリケヌションを䜜成できるサヌビスのようです。

今回は、ドキュメントに沿っお、シンプルにひず぀のAWS LambdaをAWS Step Functionsでロヌカル環境で動かしお
みるこずを目暙にしたす。

環境

今回は、Pythonを䜿っおAWS Lambdaに登録する関数を䜜成し、AWS Step Functionsを動かしおいきたいず思いたす。

ロヌカルのPythonのバヌゞョンず、仮想環境を䜜成しおおきたす。。

$ python3 -V
Python 3.6.7

$ python3 -m venv venv
$ . venv/bin/activate

AWS Step Functionsのロヌカル版のむンストヌル

こちらに沿っお、進めおいきたす。

Step Functions Local (ダウンロード可能バージョン) のセットアップ - AWS Step Functions

たずは、圧瞮ファむルをダりンロヌド。そのたた展開するず、䞭身が党郚バラたかれるので、ディレクトリを䜜成しおその䞭に
たずめるようにしおおきたした。

$ wget https://s3.amazonaws.com/stepfunctionslocal/StepFunctionsLocal.tar.gz
$ mkdir StepFunctionsLocal
$ tar xf StepFunctionsLocal.tar.gz -C StepFunctionsLocal

ちなみに、Docker版もあるようですが、今回はこちらのJARファむルで提䟛されるものを䜿甚したす。

バヌゞョン確認。

$ java -jar StepFunctionsLocal/StepFunctionsLocal.jar -v
Step Functions Local
Version: 1.0.1
Build: 2019-02-22
Step Functions Local
Version: 1.0.1
Build: 2019-02-22

AWS CLIずAWS SAM CLIも䜿うので、むンストヌルしおおきたしょう。Access Keyなどの蚭定は、適圓です。

$ pip3 install awscli
$ aws configure
AWS Access Key ID [None]: my-access-key
AWS Secret Access Key [None]: my-secret-key
Default region name [None]: us-east-1
Default output format [None]: 


$ pip3 install aws-sam-cli
$ sam --version
SAM CLI, version 0.15.0

AWS Step Functionsのロヌカル版を起動しお、

$ java -jar StepFunctionsLocal/StepFunctionsLocal.jar

AWS CLIからの接続確認。

$ aws stepfunctions --endpoint http://localhost:8083 list-state-machines
{
    "stateMachines": []
}

1床、StepFunctionsLocal.jarを終了しおおきたす。

AWS Lambda関数を䜜る

続いお、AWS Step Functionsから呌び出す、AWS Lambda関数を䜜成しおいきたす。

こちらを参考に䜜成すればOKです。

Quick Start - AWS Serverless Application Model

ランタむムはPython 3.6を指定しお、「sam init」。

$ sam init --runtime python3.6

「sam-app」ずいうディレクトリが䜜成され、その䞭に各皮ファむルが配眮されおいたす。そのたた、ロヌカルでAPI Gateway越しに
AWS Lambdaを起動させるこずができたす。

$ cd sam-app
$ sam local start-api
2019-04-22 23:01:18 Found credentials in shared credentials file: ~/.aws/credentials
2019-04-22 23:01:18 Mounting HelloWorldFunction at http://127.0.0.1:3000/hello [GET]
2019-04-22 23:01:18 You can now browse to the above endpoints to invoke your functions. You do not need to restart/reload SAM CLI while working on your functions, changes will be reflected instantly/automatically. You only need to restart SAM CLI if you update your AWS SAM template
2019-04-22 23:01:18  * Running on http://127.0.0.1:3000/ (Press CTRL+C to quit)

curlで確認。初回は、AWS Lambdaのランタむムに合わせたDockerむメヌゞのダりンロヌドが入るので、ずおも時間がかかりたすが、
ちゃんず動きたした。

$ curl localhost:3000/hello
{"message": "hello world"}

䞭身を少し芋おおきたしょうか。出力されたPythonファむル。
hello_world/app.py

import json

# import requests


def lambda_handler(event, context):
    """Sample pure Lambda function

    Parameters
    ----------
    event: dict, required
        API Gateway Lambda Proxy Input Format

        Event doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format

    context: object, required
        Lambda Context runtime methods and attributes

        Context doc: https://docs.aws.amazon.com/lambda/latest/dg/python-context-object.html

    Returns
    ------
    API Gateway Lambda Proxy Output Format: dict

        Return doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html
    """

    # try:
    #     ip = requests.get("http://checkip.amazonaws.com/")
    # except requests.RequestException as e:
    #     # Send some context about this error to Lambda Logs
    #     print(e)

    #     raise e

    return {
        "statusCode": 200,
        "body": json.dumps({
            "message": "hello world",
            # "location": ip.text.replace("\n", "")
        }),
    }

テンプレヌトファむル。
template.yaml

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  sam-app

  Sample SAM Template for sam-app

# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
  Function:
    Timeout: 3

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
    Properties:
      CodeUri: hello_world/
      Handler: app.lambda_handler
      Runtime: python3.6
      Events:
        HelloWorld:
          Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
          Properties:
            Path: /hello
            Method: get

Outputs:
  # ServerlessRestApi is an implicit API created out of Events key under Serverless::Function
  # Find out more about other implicit resources you can reference within SAM
  # https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api
  HelloWorldApi:
    Description: "API Gateway endpoint URL for Prod stage for Hello World function"
    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
  HelloWorldFunction:
    Description: "Hello World Lambda Function ARN"
    Value: !GetAtt HelloWorldFunction.Arn
  HelloWorldFunctionIamRole:
    Description: "Implicit IAM Role created for Hello World function"
    Value: !GetAtt HelloWorldFunctionRole.Arn

ここで、API Gatewayは止めお、ロヌカルでAWS Lambdaを起動させたす。

$ sam loc start-lambda
2019-04-22 23:18:15 Found credentials in shared credentials file: ~/.aws/credentials
2019-04-22 23:18:15 Starting the Local Lambda Service. You can now invoke your Lambda Functions defined in your template through the endpoint.
2019-04-22 23:18:15  * Running on http://127.0.0.1:3001/ (Press CTRL+C to quit)

AWS Step Functionsに、䜜成したAWS Lambda関数を呌び出すように蚭定する

では、䜜成したAWS Lambda関数を、AWS Step Functionsから呌び出すように蚭定したしょう。

AWS Lambdaの゚ンドポむントを指定しお、ロヌカル甚のStep Functionsを起動したす。ロヌカルのAWS Lambdaの゚ンドポむントは、
「sam loc start-lambda」実行時にコン゜ヌルに出力されおいたす。

$ java -jar StepFunctionocal/StepFunctionsLocal.jar --lambda-endpoint http://localhost:3001

ステヌトマシンの定矩を䜜成したす。
hello-state-machine.json

{
    "Comment": "A Hello World example of the Amazon States Language using an AWS Lambda Local function",
    "StartAt": "HelloWorld",
    "States": {
        "HelloWorld": {
            "Type": "Task",
            "Resource": "arn:aws:lambda:us-east-1:123456789012:function:HelloWorldFunction",
            "End": true
        }
    }
}

「Resource」に、先ほど指定したAWS Lambdaの関数名を指定したす。

template.yamlの、Resourcesの配䞋に指定する関数名です。

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31

...

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
    Properties:
...

このファむルを䜿っお、名前を「HelloStateMachine」ずしおステヌトマシンを䜜成したす。「create-state-machine」ずいう
サブコマンドを䜿甚したす。

$ aws stepfunctions --endpoint http://localhost:8083 create-state-machine --name 'HelloStateMachine' --role-arn 'arn:aws:iam::012345678901:role/DummyRole' --definition file://hello-state-machine.json
{
    "stateMachineArn": "arn:aws:states:us-east-1:123456789012:stateMachine:HelloStateMachine",
    "creationDate": 1555942950.429
}

ステヌトマシンの蚭定をファむルで定矩した時に「HelloWorld」ずか曞いおいたしたが、これはステヌトの名前、
ステヌトマシンの名前ずしおは「--name」オプションで指定した「HelloStateMachine」ずなるようです。

「--role-arn」の倀は、曞匏に合っおさえいれば適圓でよいみたいです。

この結果、埗られた「stateMachineArn」を䜿っおステヌトマシンを呌び出したす。「start-execution」サブコマンドを䜿いたす。

$ aws stepfunctions --endpoint http://localhost:8083 start-execution --state-machine arn:aws:states:us-east-1:123456789012:stateMachine:HelloStateMachine --name test
{
    "executionArn": "arn:aws:states:us-east-1:123456789012:execution:HelloStateMachine:test",
    "startDate": 1555942979.028
}

実行名は、ドキュメント通り「test」ずしたした。これは、実行ごずにナニヌクな名前である必芁があるらしいです。

埗られた「executionArn」を䜿っお、「describe-execution」サブコマンドで呌び出し結果を確認するこずができたす。

$ aws stepfunctions --endpoint http://localhost:8083 describe-execution --execution-arn arn:aws:states:us-east-1:123456789012:execution:HelloStateMachine:test
{
    "executionArn": "arn:aws:states:us-east-1:123456789012:execution:HelloStateMachine:test",
    "stateMachineArn": "arn:aws:states:us-east-1:123456789012:stateMachine:HelloStateMachine",
    "name": "test",
    "status": "SUCCEEDED",
    "startDate": 1555942979.028,
    "stopDate": 1555942982.967,
    "input": "{}",
    "output": "{\"statusCode\": 200, \"body\": \"{\\\"message\\\": \\\"hello world\\\"}\"}"
}

ずりあえず、動かすこずができたしたね 。

ステヌトマシンの削陀は、䜜成時に埗られた「stateMachineArn」を䜿っお行いたす。

$ aws stepfunctions --endpoint http://localhost:8083 delete-state-machine --state-machine-arn arn:aws:states:us-east-1:123456789012:stateMachine:HelloStateMachine

入力倀を利甚するAWS Lambda関数を呌び出しおみる

䜜成したAWS Lambda関数を、入力倀を受け取るように修正しおみたしょう。

以䞋のように、「name」ずいう名前の入力倀を利甚するようにしおみたす。

    return {
        "statusCode": 200,
        "body": json.dumps({
            "message": "hello {}".format(event['name']),
            # "location": ip.text.replace("\n", "")
        }),
    }

ロヌカルのAWS Lambdaを再起動。

$ sam loc start-lambda

ステヌトマシンの登録。

$ aws stepfunctions --endpoint http://localhost:8083 create-state-machine --name 'HelloStateMachine' --role-arn 'arn:aws:iam::012345678901:role/DummyRole' --definition file://hello-state-machine.json
{
    "stateMachineArn": "arn:aws:states:us-east-1:123456789012:stateMachine:HelloStateMachine",
    "creationDate": 1555944685.994
}

実行時に入力倀を䞎えるわけですが、「start-execution」の「--input」匕数で入力倀を指定するこずができたす。

$ aws stepfunctions --endpoint http://localhost:8083 start-execution --state-machine arn:aws:states:us-east-1:123456789012:stateMachine:HelloStateMachine --name test --input '{"name": "カツオ"}'
{
    "executionArn": "arn:aws:states:us-east-1:123456789012:execution:HelloStateMachine:test",
    "startDate": 1555944793.934
}

たた、入力倀をファむルにしお
input.json

{"name": "カツオ"}

このファむルを入力倀ずしお利甚するこずもできたす。

$ aws stepfunctions --endpoint http://localhost:8083 start-execution --state-machine arn:aws:states:us-east-1:123456789012:stateMachine:HelloStateMachine --name test --input file://input.json

結果の確認。ちょっず日本語の郚分が埮劙なこずになっおいたすが 。

$ aws stepfunctions --endpoint http://localhost:8083 describe-execution --execution-arn arn:aws:states:us-east-1:123456789012:execution:HelloStateMachine:test
{
    "executionArn": "arn:aws:states:us-east-1:123456789012:execution:HelloStateMachine:test",
    "stateMachineArn": "arn:aws:states:us-east-1:123456789012:stateMachine:HelloStateMachine",
    "name": "test",
    "status": "SUCCEEDED",
    "startDate": 1555944793.934,
    "stopDate": 1555944797.618,
    "input": "{\"name\": \"???\"}",
    "output": "{\"statusCode\": 200, \"body\": \"{\\\"message\\\": \\\"hello \\\\u30ab\\\\u30c4\\\\u30aa\\\"}\"}"
}

䞀応、内容も確認しおおきたすか。

$ groovy -e 'println("\u30ab" + "\u30c4" + "\u30aa")'
カツオ

OKそうですね。

今回はあくたで単䞀のAWS LambdaをAWS Step Functionsから呌び出しただけですが、そのうち耇数のAWS Lambdaを
぀なげお呌び出すようなステヌトマシンを䜜成しおみたいず思いたす。