はじめに
おじさんは、AWSのお勉強しています。先日購入した書籍「動かして学ぶ!Pythonサーバレスアプリ開発入門」 を読んでいたら PynamoDBを使っていたのですが、そこで躓いてしまいました。書籍のソースコードは公開されています。(翔泳社の書籍の案内ページからリンクもあります)。
PynamoDBについて、下記のサイトをざっと読みました。
NoSQLなるもので、従来のrelational DBと異なるそうです。
pynamoDBを動かした
準備
pynamodb そのものは普通に pip で入ります。
DynamoDBLocalの用意
pynamodb は DynamoDBというサーバと接続して使うもののようで、まずサーバとして動くDBが必要です。
ローカルでDBを動かすためにはいくつか方法がありますが、ここではDynamoDB Local というものを動かしました。
tar ファイルをダウンロードしてjava プログラムを実行します。
$ tar xfvz dynamodb_local_latest.tar.gz
DynamoDBLocal_lib/
DynamoDBLocal.jar
...
$ java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar -sharedDb
Initializing DynamoDB Local with the following configuration:
Port: 8000
InMemory: false
DbPath: null
SharedDb: true
shouldDelayTransientStatuses: false
CorsParams: *
実行しているディレクトリにshared-local-instance.db
というファイルがDynamoDBLocalを実行しているディレクトリにできたので、どうやらDBができたっぽいです。
(おまけ) 実は、最初 Docker image を使えば楽かと思い、こちらを試そうとしました。が、docker-compose の version 3.8の指定に対し、こちらのローカルではdocker-compose の version が 1.16.1 で、Compose 仕様を調べたところ version 3.xには未対応でした。
以下にあるように、docker-compose の定義ファイルを持ってきて docker-compose up のようなので楽だと思いましたが、実際には使えず残念。
Model の定義
本題のDBのテーブル作成と属性の追加削除を試しています。
まず pynamodb.models.Model
を継承したModel を使って定義し、pynamodb.attributes.Attribute
を継承したクラスの属性を定義します。テキストにはUnicodeAttribute, 時刻にはUTCDateTimeAttribute などが用意されています。
from pynamodb.models import Model
from pynamodb.attributes import (
UnicodeAttribute, NumberAttribute, UnicodeSetAttribute, UTCDateTimeAttribute
)
from datetime import datetime
class MyInheritedModel(Model):
class Meta:
table_name = 'Thread'
region = 'us-west-1' # Specifies the region
# Optional: Specify the hostname only if it needs to be changed from the default AWS setting
host = 'http://localhost'
write_capacity_units = 10
read_capacity_units = 10
textMsg = UnicodeAttribute(hash_key=True)
views = NumberAttribute(default=0)
tags = UnicodeSetAttribute()
isChecked = BooleanAttribute(null=False, default=False)
createdAt = UTCDateTimeAttribute(null=False, default=datetime.now())
テーブル作成
定義したモデルのテーブルを作成します。AWSでなくローカルで動かすときはhost を指定します。引数にwait を指定すると、テーブル作成が終了するまでblock されます。
from mymodel import MyInheritedModel
if not MyInheritedModel.exists():
MyInheritedModel.create_table(read_capacity_units=2, write_capacity_units=2, wait=True)
DBに登録
いよいよDBを使ってみます。
- 登録はclass のインスタンスを作って
.save()
それば良いようです。 - 登録要素の取得は、はmodel に対して
.get()
で取得できました。query の使い方は別にあり、奥が深いようです。 - 全ての要素を触るには
.sacan()
でできました。DBをCSVに保存したいなー、と思ったのですが、方法が分からなかったので、これを使いました。
scan() で全てを参照するiterator を取得できるようなので、一つ一つ書き足していくことはできました。
from mymodel import MyInheritedModel
from datetime import datetime
for i in range(10):
msg = f"message{i}"
myitem = MyInheritedModel(textMsg=msg, tags="v0")
myitem.save()
print(f"add msg={msg}, db count={MyInheritedModel.count()}")
try:
key_msg = "message5"
itm = MyInheritedModel.get(key_msg)
print(f"{key_msg} is created at {itm.createdAt}")
except MyInheritedModel.DoesNotExist as e:
print(e)
scaned = MyInheritedModel.scan()
for itm in scaned:
print(itm.textMsg, itm.createdAt)
実行結果です。
$ python3 item_test.py
add msg=message0, db count=10
add msg=message1, db count=10
add msg=message2, db count=10
add msg=message3, db count=10
add msg=message4, db count=10
add msg=message5, db count=10
add msg=message6, db count=10
add msg=message7, db count=10
add msg=message8, db count=10
add msg=message9, db count=10
message5 is created at 2021-10-24 19:15:51.752361+00:00
message2 2021-10-24 19:15:51.752361+00:00
message6 2021-10-24 19:15:51.752361+00:00
message5 2021-10-24 19:15:51.752361+00:00
message8 2021-10-24 19:15:51.752361+00:00
message4 2021-10-24 19:15:51.752361+00:00
message0 2021-10-24 19:15:51.752361+00:00
message1 2021-10-24 19:15:51.752361+00:00
message3 2021-10-24 19:15:51.752361+00:00
message9 2021-10-24 19:15:51.752361+00:00
message7 2021-10-24 19:15:51.752361+00:00
Logging
python の logging が使えます。
import logging
logging.basicConfig()
log = logging.getLogger("pynamodb")
log.setLevel(logging.DEBUG)
log.propagate = True
まとめ
とりあえず、ローカルでAWSで使われているDynamoDBと同じ形のDBのサーバを動かすことができた。
モデルを定義しテーブルを作成し、アイテムを登録し、全データを取得できた。
次のステップとしては、
- いよいよAWSで動かす
- query の使い方をマスターする
かな。まだDBまともに使ったことないし。
参考情報
(2021/10/25)