[英]Acquiring pool connections in Python Gino (async)
I'm using Postgres, Python3.7 with asyncio
+ asyncpg
+ gino
(ORM-ish) + aiohttp
(routing, web responses).我正在使用 Postgres、Python3.7 和
asyncio
+ asyncpg
+ gino
(ORM-ish) + aiohttp
(路由,web 响应)。
I created a small postgres table users
in my database testdb
and inserted a single row:我在我的数据库
testdb
中创建了一个小的 postgres 表users
并插入了一行:
testdb=# select * from users;
id | nickname
----+----------
1 | fantix
I'm trying to set up my database such that I can make use of the ORM within routes as requests come in.我正在尝试设置我的数据库,以便在请求进入时可以在路由中使用 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}')
The output is: output 是:
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: [()]
which is strange.这很奇怪。 The "explicit" code essentially runs a bare
SELECT
against the database, which is useless. “显式”代码本质上是针对数据库运行一个裸露的
SELECT
,这是没有用的。
I can't find in the documentation a way to both 1) use the ORM, and 2) explicitly check out connections from the pool.我在文档中找不到两种方法:1)使用 ORM,2)明确检查池中的连接。
Questions I have:我的问题:
await User.query.gino.all()
check out a connection from the pool? await User.query.gino.all()
是否从池中签出连接? How is it released? I'd essentially like the explicitness of the style in test_engine_explicit()
to work with Gino, but perhaps I'm just not understanding how the Gino ORM works.我本质上希望
test_engine_explicit()
中的明确风格与 Gino 一起工作,但也许我只是不明白 Gino ORM 是如何工作的。
I have never used GINO before, but after a quick look into the code:我以前从未使用过 GINO,但在快速查看代码后:
User.select()
, then it adds nothing to that.User.select()
,那么它不会增加任何内容。User.query.gino.all()
, but maintaining connection yourself, then you could follow the docs and use User.query
instead of plain User.select()
:User.query.gino.all()
相同的效果,但要自己维护连接,那么您可以按照文档并使用User.query
而不是普通的User.select()
:async with engine.acquire() as conn:
return await conn.all(User.query)
Just tested and it works fine for me.刚刚测试过,对我来说效果很好。
Regarding the connections pool, I am not sure that I got the question correctly, but Engine.acquire
creates a reusable connection by default and then it is added to the pool, which is actually a stack:关于连接池,我不确定我的问题是否正确,但
Engine.acquire
默认创建一个可重用连接,然后将其添加到池中,实际上是一个堆栈:
:param reusable: Mark this connection as reusable or otherwise. This has no effect if it is a reusing connection. All reusable connections are placed in a stack, any reusing acquire operation will always reuse the top (latest) reusable connection. One reusable connection may be reused by several reusing connections - they all share one same underlying connection. Acquiring a connection with ``reusable=False`` and ``reusing=False`` makes it a cleanly isolated connection which is only referenced once here.
There is also a manual transaction control in GINO, so eg you can create a non-reusable, non-reuse connection and control transaction flow manually: GINO 中还有一个手动事务控制,例如,您可以创建一个不可重用、不可重用的连接并手动控制事务流:
async with engine.acquire(reuse=False, reusable=False) as conn:
tx = await conn.transaction()
try:
await conn.status("INSERT INTO users(nickname) VALUES('e')")
await tx.commit()
except Exception:
await tx.rollback()
raise
As for connection release, I cannot find any evidence that GINO releases connections itself.至于连接释放,我找不到任何证据表明GINO自己释放连接。 I guess that pool is maintained by SQLAlchemy core.
我猜这个池是由 SQLAlchemy 核心维护的。
I definitely have not answered your questions directly, but hope it will help you somehow.我肯定没有直接回答你的问题,但希望它能以某种方式帮助你。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.