「動かして学ぶ!Pythonサーバレスアプリ開発入門」のサンプルコードです。
Table of Contents
- 概要
- 誤字
- 本書で利用しているライブラリの全バージョン
- QA
- 1.Flask-Scriptがインストールできない
- 2.flask-loginのインストール時にコンフリクトが発生する
- 3.zappaのインストール時にコンフリクトが発生する
- 4.zappa deploy実行時にエラーが発生する
- 5. P177の python manage.py init_db で 「Unable to locate credentials」エラーが発生する
- 6. 10章にてzappa deploy時に
Error: Warning! Status check on the deployed lambda failed. A GET request to '/' yielded a 502 response code.
が発生するが動作に問題ないか - 7. P146で「これまでセッション情報はローカルに保存していましたが」とあるものの、これまでセッションのコードは出てきていないためどの箇所で利用しているのか
- 8. P157の
.bashrc
の環境変数はP.175でzappa_settings.json
で設定しているので不要ではないか - 9. Mac M1を使っている場合にどのPythonバージョンをインストールすればよいか
- 10. P177でpython manage.py init_dbを実行すると 「AccessDeniedException」エラーが発生する
application
: 最終版(本書読了時)のサーバレスBlogアプリケーションserverless-bot
: 最終版(本書読了時)のサーバレスBotsnippets
: 本文中のリストのスニペット(例:リスト6.2 -> list.6.2.txt)chapXX
: 各章終了時のサンプルアプリケーション
zappa_settings.json
はzappa_settings.json.sample
としてサンプルを置いております。
変更後の箇所は以下になります。(詳細はこちらをご覧ください)
~/.bashrc
AWS_ACCESS_KEY_ID = 'AWS_ACCESS_KEY_ID'
application/flask_blog/models/entries.py
aws_access_key_id = app.config.get('AWS_ACCESS_KEY_ID')
application/flask_blog/models/sessions.py
aws_access_key_id = app.config.get('AWS_ACCESS_KEY_ID')
application/flask_blog/config.py
class DevelopmentConfig(Config):
....
AWS_ACCESS_KEY_ID = 'AWS_ACCESS_KEY_ID'
....
SESSION_DYNAMODB_KEY_ID = AWS_ACCESS_KEY_ID
....
class ProductionConfig(Config):
....
AWS_ACCESS_KEY_ID = os.environ.get('SERVERLESS_AWS_ACCESS_KEY_ID')
....
SESSION_DYNAMODB_KEY_ID = AWS_ACCESS_KEY_ID
本書で利用しているライブラリの全バージョンです。
ライブラリのインストール時にコンフリクトが発生する際は、本バージョンを参考に以下のコマンドでバージョンを指定してインストールしてください。
# 例
pipenv install "flask-login==0.5.0"
Flask-Login==0.5.0
- Flask [required: Any, installed: 1.1.2]
- click [required: >=5.1, installed: 7.1.2]
- itsdangerous [required: >=0.24, installed: 1.1.0]
- Jinja2 [required: >=2.10.1, installed: 2.11.3]
- MarkupSafe [required: >=0.23, installed: 1.1.1]
- Werkzeug [required: >=0.15, installed: 0.16.1]
Flask-Script==2.0.6
- Flask [required: Any, installed: 1.1.2]
- click [required: >=5.1, installed: 7.1.2]
- itsdangerous [required: >=0.24, installed: 1.1.0]
- Jinja2 [required: >=2.10.1, installed: 2.11.3]
- MarkupSafe [required: >=0.23, installed: 1.1.1]
- Werkzeug [required: >=0.15, installed: 0.16.1]
Flask-Sessionstore==0.4.5
- Flask [required: >=0.8, installed: 1.1.2]
- click [required: >=5.1, installed: 7.1.2]
- itsdangerous [required: >=0.24, installed: 1.1.0]
- Jinja2 [required: >=2.10.1, installed: 2.11.3]
- MarkupSafe [required: >=0.23, installed: 1.1.1]
- Werkzeug [required: >=0.15, installed: 0.16.1]
pynamodb==5.0.3
- botocore [required: >=1.12.54, installed: 1.20.62]
- jmespath [required: >=0.7.1,<1.0.0, installed: 0.10.0]
- python-dateutil [required: >=2.1,<3.0.0, installed: 2.8.1]
- six [required: >=1.5, installed: 1.15.0]
- urllib3 [required: >=1.25.4,<1.27, installed: 1.26.4]
zappa==0.52.0
- argcomplete [required: Any, installed: 1.12.3]
- boto3 [required: Any, installed: 1.17.62]
- botocore [required: >=1.20.62,<1.21.0, installed: 1.20.62]
- jmespath [required: >=0.7.1,<1.0.0, installed: 0.10.0]
- python-dateutil [required: >=2.1,<3.0.0, installed: 2.8.1]
- six [required: >=1.5, installed: 1.15.0]
- urllib3 [required: >=1.25.4,<1.27, installed: 1.26.4]
- jmespath [required: >=0.7.1,<1.0.0, installed: 0.10.0]
- s3transfer [required: >=0.4.0,<0.5.0, installed: 0.4.2]
- botocore [required: >=1.12.36,<2.0a.0, installed: 1.20.62]
- jmespath [required: >=0.7.1,<1.0.0, installed: 0.10.0]
- python-dateutil [required: >=2.1,<3.0.0, installed: 2.8.1]
- six [required: >=1.5, installed: 1.15.0]
- urllib3 [required: >=1.25.4,<1.27, installed: 1.26.4]
- durationpy [required: Any, installed: 0.5]
- future [required: Any, installed: 0.18.2]
- hjson [required: Any, installed: 3.0.2]
- jmespath [required: Any, installed: 0.10.0]
- kappa [required: ==0.6.0, installed: 0.6.0]
- boto3 [required: >=1.2.3, installed: 1.17.62]
- botocore [required: >=1.20.62,<1.21.0, installed: 1.20.62]
- jmespath [required: >=0.7.1,<1.0.0, installed: 0.10.0]
- python-dateutil [required: >=2.1,<3.0.0, installed: 2.8.1]
- six [required: >=1.5, installed: 1.15.0]
- urllib3 [required: >=1.25.4,<1.27, installed: 1.26.4]
- jmespath [required: >=0.7.1,<1.0.0, installed: 0.10.0]
- s3transfer [required: >=0.4.0,<0.5.0, installed: 0.4.2]
- botocore [required: >=1.12.36,<2.0a.0, installed: 1.20.62]
- jmespath [required: >=0.7.1,<1.0.0, installed: 0.10.0]
- python-dateutil [required: >=2.1,<3.0.0, installed: 2.8.1]
- six [required: >=1.5, installed: 1.15.0]
- urllib3 [required: >=1.25.4,<1.27, installed: 1.26.4]
- click [required: >=5.1, installed: 7.1.2]
- placebo [required: >=0.8.1, installed: 0.9.0]
- PyYAML [required: >=3.11, installed: 5.4.1]
- pip [required: >=9.0.1, installed: 21.1.2]
- pip-tools [required: Any, installed: 6.1.0]
- click [required: >=7, installed: 7.1.2]
- pep517 [required: Any, installed: 0.10.0]
- toml [required: Any, installed: 0.10.2]
- pip [required: >=20.3, installed: 21.1.2]
- python-dateutil [required: Any, installed: 2.8.1]
- six [required: >=1.5, installed: 1.15.0]
- python-slugify [required: Any, installed: 5.0.0]
- text-unidecode [required: >=1.3, installed: 1.3]
- PyYAML [required: Any, installed: 5.4.1]
- requests [required: >=2.20.0, installed: 2.25.1]
- certifi [required: >=2017.4.17, installed: 2020.12.5]
- chardet [required: >=3.0.2,<5, installed: 4.0.0]
- idna [required: >=2.5,<3, installed: 2.10]
- urllib3 [required: >=1.21.1,<1.27, installed: 1.26.4]
- six [required: Any, installed: 1.15.0]
- toml [required: Any, installed: 0.10.2]
- tqdm [required: Any, installed: 4.60.0]
- troposphere [required: Any, installed: 2.7.1]
- cfn-flip [required: >=1.0.2, installed: 1.2.3]
- Click [required: Any, installed: 7.1.2]
- PyYAML [required: >=4.1, installed: 5.4.1]
- six [required: Any, installed: 1.15.0]
- Werkzeug [required: <1.0, installed: 0.16.1]
- wheel [required: Any, installed: 0.36.2]
- wsgi-request-logger [required: Any, installed: 0.4.6]
gspread==3.7.0
- google-auth [required: >=1.12.0, installed: 1.30.0]
- cachetools [required: >=2.0.0,<5.0, installed: 4.2.2]
- pyasn1-modules [required: >=0.2.1, installed: 0.2.8]
- pyasn1 [required: >=0.4.6,<0.5.0, installed: 0.4.8]
- rsa [required: >=3.1.4,<5, installed: 4.7.2]
- pyasn1 [required: >=0.1.3, installed: 0.4.8]
- setuptools [required: >=40.3.0, installed: 57.4.0]
- six [required: >=1.9.0, installed: 1.15.0]
- google-auth-oauthlib [required: >=0.4.1, installed: 0.4.4]
- google-auth [required: >=1.0.0, installed: 1.30.0]
- cachetools [required: >=2.0.0,<5.0, installed: 4.2.2]
- pyasn1-modules [required: >=0.2.1, installed: 0.2.8]
- pyasn1 [required: >=0.4.6,<0.5.0, installed: 0.4.8]
- rsa [required: >=3.1.4,<5, installed: 4.7.2]
- pyasn1 [required: >=0.1.3, installed: 0.4.8]
- setuptools [required: >=40.3.0, installed: 57.4.0]
- six [required: >=1.9.0, installed: 1.15.0]
- requests-oauthlib [required: >=0.7.0, installed: 1.3.0]
- oauthlib [required: >=3.0.0, installed: 3.1.0]
- requests [required: >=2.0.0, installed: 2.25.1]
- certifi [required: >=2017.4.17, installed: 2020.12.5]
- chardet [required: >=3.0.2,<5, installed: 4.0.0]
- idna [required: >=2.5,<3, installed: 2.10]
- urllib3 [required: >=1.21.1,<1.27, installed: 1.26.4]
oauth2client==4.1.3
- httplib2 [required: >=0.9.1, installed: 0.19.1]
- pyparsing [required: >=2.4.2,<3, installed: 2.4.7]
- pyasn1 [required: >=0.1.7, installed: 0.4.8]
- pyasn1-modules [required: >=0.0.5, installed: 0.2.8]
- pyasn1 [required: >=0.4.6,<0.5.0, installed: 0.4.8]
- rsa [required: >=3.1.4, installed: 4.7.2]
- pyasn1 [required: >=0.1.3, installed: 0.4.8]
- six [required: >=1.6.1, installed: 1.15.0]
pytz==2021.1
slack-sdk==3.5.1
zappa==0.52.0
- argcomplete [required: Any, installed: 1.12.3]
- boto3 [required: Any, installed: 1.17.62]
- botocore [required: >=1.20.62,<1.21.0, installed: 1.20.62]
- jmespath [required: >=0.7.1,<1.0.0, installed: 0.10.0]
- python-dateutil [required: >=2.1,<3.0.0, installed: 2.8.1]
- six [required: >=1.5, installed: 1.15.0]
- urllib3 [required: >=1.25.4,<1.27, installed: 1.26.4]
- jmespath [required: >=0.7.1,<1.0.0, installed: 0.10.0]
- s3transfer [required: >=0.4.0,<0.5.0, installed: 0.4.2]
- botocore [required: >=1.12.36,<2.0a.0, installed: 1.20.62]
- jmespath [required: >=0.7.1,<1.0.0, installed: 0.10.0]
- python-dateutil [required: >=2.1,<3.0.0, installed: 2.8.1]
- six [required: >=1.5, installed: 1.15.0]
- urllib3 [required: >=1.25.4,<1.27, installed: 1.26.4]
- durationpy [required: Any, installed: 0.5]
- future [required: Any, installed: 0.18.2]
- hjson [required: Any, installed: 3.0.2]
- jmespath [required: Any, installed: 0.10.0]
- kappa [required: ==0.6.0, installed: 0.6.0]
- boto3 [required: >=1.2.3, installed: 1.17.62]
- botocore [required: >=1.20.62,<1.21.0, installed: 1.20.62]
- jmespath [required: >=0.7.1,<1.0.0, installed: 0.10.0]
- python-dateutil [required: >=2.1,<3.0.0, installed: 2.8.1]
- six [required: >=1.5, installed: 1.15.0]
- urllib3 [required: >=1.25.4,<1.27, installed: 1.26.4]
- jmespath [required: >=0.7.1,<1.0.0, installed: 0.10.0]
- s3transfer [required: >=0.4.0,<0.5.0, installed: 0.4.2]
- botocore [required: >=1.12.36,<2.0a.0, installed: 1.20.62]
- jmespath [required: >=0.7.1,<1.0.0, installed: 0.10.0]
- python-dateutil [required: >=2.1,<3.0.0, installed: 2.8.1]
- six [required: >=1.5, installed: 1.15.0]
- urllib3 [required: >=1.25.4,<1.27, installed: 1.26.4]
- click [required: >=5.1, installed: 7.1.2]
- placebo [required: >=0.8.1, installed: 0.9.0]
- PyYAML [required: >=3.11, installed: 5.4.1]
- pip [required: >=9.0.1, installed: 21.2.4]
- pip-tools [required: Any, installed: 6.1.0]
- click [required: >=7, installed: 7.1.2]
- pep517 [required: Any, installed: 0.10.0]
- toml [required: Any, installed: 0.10.2]
- pip [required: >=20.3, installed: 21.2.4]
- python-dateutil [required: Any, installed: 2.8.1]
- six [required: >=1.5, installed: 1.15.0]
- python-slugify [required: Any, installed: 5.0.0]
- text-unidecode [required: >=1.3, installed: 1.3]
- PyYAML [required: Any, installed: 5.4.1]
- requests [required: >=2.20.0, installed: 2.25.1]
- certifi [required: >=2017.4.17, installed: 2020.12.5]
- chardet [required: >=3.0.2,<5, installed: 4.0.0]
- idna [required: >=2.5,<3, installed: 2.10]
- urllib3 [required: >=1.21.1,<1.27, installed: 1.26.4]
- six [required: Any, installed: 1.15.0]
- toml [required: Any, installed: 0.10.2]
- tqdm [required: Any, installed: 4.60.0]
- troposphere [required: Any, installed: 2.7.1]
- cfn-flip [required: >=1.0.2, installed: 1.2.3]
- Click [required: Any, installed: 7.1.2]
- PyYAML [required: >=4.1, installed: 5.4.1]
- six [required: Any, installed: 1.15.0]
- Werkzeug [required: <1.0, installed: 0.16.1]
- wheel [required: Any, installed: 0.36.2]
- wsgi-request-logger [required: Any, installed: 0.4.6]
現時点(2021/07/20)のFlask-Scriptの最新バージョンにて、Flask2.0との組み合わせでバグ報告が上がっております。
$ python manage.py init_db
Traceback (most recent call last):
File "C:\Users\xxx\workspace\python-serverless\application\manage.py", line 1, in <module>
from flask_script import Manager
File "C:\Users\xxx\.virtualenvs\application-rWZzxA8f\lib\site-packages\flask_script\__init__.py", line 15, in <module>
from flask._compat import text_type
ModuleNotFoundError: No module named 'flask._compat'
以下のコマンドで、下記のライブラリをバージョン指定でインストールしてください。
pipenv install "Flask==1.1.2"
pipenv install "jinja2==2.11.3"
pipenv install "itsdangerous==1.1.0"
pipenv install "werkzeug==0.16.1"
pipenv install "markupsafe==1.1.1"
その後、Flask-Scriptのインストールが可能になります。
以下のコマンドで、バージョン0.5.0を指定してインストールしてください。
pipenv install "flask-login==0.5.0"
現時点(2021/07/20)のzappaの最新バージョン(0.53.0)では、Flaskバージョン1.0系にのみ対応しております。
そのため、Flaskバージョン2.0以上をインストールしている場合にはコンフリクトが発生します。
Flaskバージョンを本書記載の1.1.2でインストールしてください。
pipenv install "Flask==1.1.2"
その後、zappaのインストールが可能になります。
zappaの関連ライブラリのアップデートにより、zappaにて以下のエラーが発生しております。
Traceback (most recent call last):
File "/Users/hondatakatomo/.local/share/virtualenvs/application-tAyQEiLX/lib/python3.8/site-packages/zappa/cli.py", line 3422, in handle
sys.exit(cli.handle())
File "/Users/hondatakatomo/.local/share/virtualenvs/application-tAyQEiLX/lib/python3.8/site-packages/zappa/cli.py", line 588, in handle
self.dispatch_command(self.command, stage)
File "/Users/hondatakatomo/.local/share/virtualenvs/application-tAyQEiLX/lib/python3.8/site-packages/zappa/cli.py", line 630, in dispatch_command
self.deploy(self.vargs["zip"], self.vargs["docker_image_uri"])
File "/Users/hondatakatomo/.local/share/virtualenvs/application-tAyQEiLX/lib/python3.8/site-packages/zappa/cli.py", line 952, in deploy
template = self.zappa.create_stack_template(
File "/Users/hondatakatomo/.local/share/virtualenvs/application-tAyQEiLX/lib/python3.8/site-packages/zappa/core.py", line 2417, in create_stack_template
self.cf_template.add_description("Automatically generated with Zappa")
AttributeError: 'Template' object has no attribute 'add_description'
該当のzappa関連ライブラリであるtroposphere
を、以下のバージョン指定でインストールしてください。
pipenv install "troposphere==2.7.1"
その後、すでにzappa deploy
を実施していた場合は一度undeploy
してから再度deploy
してください。
zappa undeploy dev
zappa deploy dev
2021/08/04時点でのzappa最新バージョン0.53.0では未対応ですが 現在修正対応中のため、今後はzappaの最新バージョンにてエラーが発生しないよう対応される見込みです。 随時こちらでも情報をアップデートさせていただきます。
環境変数が正しく読み込まれていないことが原因になります。
...
botocore.exceptions.NoCredentialsError: Unable to locate credentials
...
以下の5つの環境変数が正しく設定されているか確認してみてください。
「誤字」の項での値が正しく直っているか(ACEESS
-> ACCESS
)も再度ご確認ください。
SERVERLESS_BLOG_CONFIG
SERVERLESS_USER_PW
SERVERLESS_SECRET_KEY
SERVERLESS_AWS_ACCESS_KEY_ID
SERVERLESS_AWS_SECRET_KEY
設定後、windowsを再起動して環境変数が読み込まれているか確認してみてください。
6. 10章にてzappa deploy時にError: Warning! Status check on the deployed lambda failed. A GET request to '/' yielded a 502 response code.
が発生するが動作に問題ないか
Zappaのデフォルトでは、Webアプリケーションも動くことを想定しているため エンドポイントが存在しない場合、つまり10章のスクリプトだけの場合には上記のWarningが表示されますが、動作に問題はございません。
もしWarningを消したい場合は、Configにて以下の設定を加えることで表示されなくなります。
{
"dev": {
"apigateway_enabled": false,
....
}
}
本書ではWarning非表示のための設定を追記することでチュートリアルが煩雑になることを防ぐため、あえて注釈での説明のみにとどめておりましたが、こちらで追加説明させていただきます。
前章8章の「ログイン機能を導入する」のところですが、前提としてログイン機能の実現にはセッションが必要となります。
そのため、Flask-login
が内部的にFlaskのsession機構を利用しております。
ご質問の通り明示的な操作として出てきていなかったため、こちらにて補足させていただきます。
.bashrc
の環境変数ですが2つの理由で作成しております。
1つめは、ローカルで本番用データベースの作成コマンドを実行するためです。
2つめは、それぞれの環境で動作確認および切り分けしながらステップごとに進められるよう用意しました。
- ローカル環境でDyanmoDB localで動作確認
- ローカル環境で本番DynamoDBでの動作確認
- サーバレス環境で本番DynamoDBでの動作確認
問題があったときにどの環境まで正しく動作しているか切り分けたり、 コードをアップデートしたときに順に動作確認することで急に大きな問題が発生することを防いだり、 また本書の構成としてステップごとに学んでいただけるようにというコンセプトも理由としてございます。
Support macOS 11 and Apple Silicon Macsにあるとおり、Python3.8以降ではM1もサポートされています。
Python3.9以降を新規で使いたい場合はリリースニュースである通り Apple Siliconに対応したuniversal版のインストーラーをお使いください。
本書では、2つのIAMユーザを作成しております。
flask-blog-dynamodb
: DynamoDBを操作するためのIAMユーザzappa-exec-user
: Zappaを使ってサーバレスにデプロイするためのIAMユーザ
init_db
はDynamoDBの操作のため、zappa-exec-user
ではなくflask-blog-dynamodb
が使われているかをご確認ください。
また、権限を追加することで、1つのIAMユーザのみですべての操作を行うことも可能です。 本書では締切の関係上掲載できなかったため、興味がありましたら元となっておりますPythonで作るはじめてのサーバレスアプリケーションも合わせてご参考ください。