5
6

More than 1 year has passed since last update.

【AWS】PynamoDBを使ってみる

Last updated at Posted at 2021-10-25

はじめに

おじさんは、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 などが用意されています。

mymodel.py
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 を取得できるようなので、一つ一つ書き足していくことはできました。
item_test.py
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)

5
6
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
5
6