python のランタイムでデバッグする場合、以下のような注意書きがあったり、Visual Studio Code でリモートデバッグするときは
ptvsd
を使う等いろいろあったのでメモ.
SAM ローカルを使用してサーバーレスアプリケーションをローカルでテストする - AWS Lambda
Python で記述された関数のデバッグ
Node.js や Java とは異なり、Python では Lambda 関数コードでリモートデバッグを有効にする必要があります。Python ランタイム (2.7 または 3.6) のいずれかを使用する関数に対して (上述の --debug-port オプションまたは -d オプションを使用して) デバッグを有効にすると、SAM Local はそのポートを通じてホストマシンから Lambda コンテナへのマッピングを行います。リモートデバッグを有効にするには、remote-pdb などの Python パッケージを使用します。
適当なディレクトリを作成し、以下のような template.yml
と products.py
を保存.
template.yml
AWSTemplateFormatVersion : '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: My first serverless application(debug).
Resources:
Products:
Type: AWS::Serverless::Function
Properties:
Handler: products.lambda_handler
Runtime: python3.6
Events:
ListProducts:
Type: Api
Properties:
Path: /products
Method: get
products.py
def lambda_handler(event, context):
response = {
"statusCode": 200,
"headers": {
"my_header": "my_value"
},
"body": event['queryStringParameters']['key1'] + ':test',
"isBase64Encoded": False
}
return response
$ sam localt start-api
を実行した後に、$ curl http://127.0.0.1:3000/products?key1=foo
を実行.
foo:test
が返ってくることを確認する.
Visual Stduio Code + Python でリモートデバッグする場合は、ptvsd
を利用することになっているようなのでインストールする.
なお、インストールにあたっては以下のような注意点がある.
- 現時点で
pip install ptvsd
を実行すると 3.2.1 がインストールされるが、Visual Studio Code + Python では 3.0.0 までのプロトコルにしか対応していない. - AWS Lambda 用にサードパーティライブラリをインストール場合には、関数のソースと同じディレクトリに配置する.
これらを踏まえて、ptvsd
は以下のようにインストールする.
$ pip install ptvsd==3.0.0 -t /path/to/project-dir
なお、環境によっては、エラーでインストールできないときがある.
とりあえず以下のように --system
を指定することで回避できることもある.
$ pip install ptvsd==3.0.0 -t /path/to/project-dir --system
参考:
- Debugging Python with Visual Studio Code
- Update documentation to ensure version 3.0.0 (not later) of PTVSD is installed for debugging · Issue #514 · Microsoft/vscode-python · GitHub
- デプロイパッケージの作成 (Python) - AWS Lambda
- --target does not work with --user · Issue #3826 · pypa/pip · GitHub
- #830892 - python-pip defaults to --user, breaks upstream --target option - Debian Bug report logs
template.yml
に以下のように環境変数の定義を追加する.
AWSTemplateFormatVersion : '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: My first serverless application(debug).
Resources:
Products:
Type: AWS::Serverless::Function
Properties:
Handler: products.lambda_handler
Runtime: python3.6
Environment:
Variables:
PTVSD: "off"
Events:
ListProducts:
Type: Api
Properties:
Path: /products
Method: get
products.py
に以下のようにコードを追加する.
なお、インターフェースの指定は 127.0.0.1
ではなく 0.0.0.0
にする必要がある(らしい).
def lambda_handler(event, context):
from os import environ
if environ.get('PTVSD', '') == 'on':
import ptvsd
ptvsd.enable_attach(secret="my_secret", address=('0.0.0.0', 5959))
ptvsd.wait_for_attach()
response = {
"statusCode": 200,
"headers": {
"my_header": "my_value"
},
"body": event['queryStringParameters']['key1'] + ':test',
"isBase64Encoded": False
}
return response
Visual Studio Code で関数のディレクトリをオープンした後に、デバッグビューへ切り替える.
歯車アイコンをクリックし launch.json
が編集できるようになったら、以下のような記述を追加する.
設定のポイントとしては、「port
を上記の接続待ちポートにあわせる」「remoteRoot
を /var/task
にする」.
{
"name": "Attach (Remote SAM Debug)",
"type": "python",
"request": "attach",
"localRoot": "${workspaceFolder}",
"remoteRoot": "/var/task",
"port": 5858,
"secret": "my_secret",
"host": "localhost"
},
SAM ローカルを以下のように(シェル変数 PTVSD
と -d
オプション付き)で起動する.
$ PTVSDN=on sam-local start-api -d 5858
関数を以下のように起動する。なお、今回はデバッガが動作していることを確認するために key1
ではなく key2
を指定している.
$ curl http://127.0.0.1:3000/products?key2=foo
Visual Studio Code のデバッグビューで BREAKPOINTS セクションの「All Exceptions」をチェック、その後、上記で追加した接続設定でデバッグを開始する.
これで、key1
にアクセスしようとしてエラーになったところで停止している状態になるので、
event['queryStringParameters']
の内容等を確認してみる.
- BREAKPOINT がうまく動作しない.
これは SAM ローカルとの組み合わせだけの問題ではないのだが、
(以前にも ntvsd
を使ったときに BREAKPOINTS の指定が効いたり効かなかったり等があった).
とりあえず、execption 補足はできるようなので、当面はその辺を利用することになるかも.
ptvsd
関連の設定やコードが残ってしまう.
まだ、デプロイパッケージの作成等は試していないので予想になってしまうが、おそらくは、
パッケージ化する(zip に固める)ときには ptvsd
を削除するか除外する必要がある.
また、ptvsd
で接続待ちにするコードも記述されたままになるので、その辺の扱いはどのようにするのか
(いまのところは環境変数で切り替えるようにしているが、それで良いのか?).
ptvsd
の扱いについては、ptvsd
インストール済のローカルイメージを作成し、
sam local start-api
開始時に --skip-pull-image
を指定するという方法もありそうだが、それはそれでイメージのメンテ等の手間が増えそうなので、出来ることなら避けたい手順である.
SAM ローカルを起動した環境と Docker ホストが異る構成になっている場合、
-d
で指定したポートは Docker ホスト側にマッピングされることになる.
よって、SAM ローカルを起動した環境で Visual Studio Code を起動した場合は、
接続先の host
の指定を Docker ホストにする(あるいはコンテナを直接指定してしまう)等、
構成にあわせて変更する必要がある.