3

asyncio+ asyncpg+ gino(ORM 風) + aiohttp(ルーティング、Web 応答)で Postgres、Python3.7 を使用しています。

usersデータベースに小さな postgres テーブルを作成しtestdb、単一の行を挿入しました。

testdb=# select * from users;
 id | nickname
----+----------
  1 | fantix

リクエストが入ったときにルート内でORMを利用できるようにデータベースをセットアップしようとしています.

import time
import asyncio
import gino

DATABASE_URL = os.environ.get('DATABASE_URL')

db = gino.Gino()

class User(db.Model):
  __tablename__ = 'users'
  id = db.Column(db.Integer(), primary_key=True)
  nickname = db.Column(db.Unicode(), default='noname')

kwargs = dict(
  min_size=10,
  max_size=100,
  max_queries=1000,
  max_inactive_connection_lifetime=60 * 5,
  echo=True
)

async def test_engine_implicit():
  await db.set_bind(DATABASE_URL, **kwargs)
  return await User.query.gino.all()      # this works

async def test_engine_explicit():
  engine = await gino.create_engine(DATABASE_URL, **kwargs)
  db.bind = engine
  async with engine.acquire() as conn:
    return await conn.all(User.select())  # this doesn't work!

users = asyncio.get_event_loop().run_until_complete(test_engine_implicit())
print(f'implicit query: {users}')

users = asyncio.get_event_loop().run_until_complete(test_engine_explicit())
print(f'explicit query: {users}')

出力は次のとおりです。

web_1    | INFO gino.engine._SAEngine SELECT users.id, users.nickname FROM users
web_1    | INFO gino.engine._SAEngine ()
web_1    | implicit query: [<db.User object at 0x7fc57be42410>]
web_1    | INFO gino.engine._SAEngine SELECT
web_1    | INFO gino.engine._SAEngine ()
web_1    | explicit query: [()]

これは奇妙です。「明示的な」コードは、基本的SELECTにデータベースに対して実行されますが、これは役に立ちません。

ドキュメントには、1) ORM を使用する方法と、2) プールからの接続を明示的にチェックアウトする方法が見つかりません。

私が持っている質問:

  1. await User.query.gino.all()プールから接続をチェックアウトしますか? どのようにリリースされますか?
  2. クエリをトランザクションでラップするにはどうすればよいですか? プールから接続をいつ/どこで取得し、どのように解放するかを明示的に制御できないことに不安を感じています。

私は基本的に、test_engine_explicit()Gino で動作するスタイルの明示性を望んでいますが、Gino ORM がどのように機能するかを理解していないだけかもしれません。

4

1 に答える 1