首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Python中获取池连接(异步)

在Python中获取池连接(异步)
EN

Stack Overflow用户
提问于 2019-10-30 01:19:14
回答 1查看 1.9K关注 0票数 3

我使用Postgres,Python3.7和asyncio + asyncpg + gino (ORM)+ aiohttp (路由,web响应)。

我在数据库users中创建了一个小型postgres表testdb,并插入了一行:

代码语言:javascript
复制
testdb=# select * from users;
 id | nickname
----+----------
  1 | fantix

我正在尝试设置我的数据库,以便当请求传入时,我可以在路由中使用ORM。

代码语言:javascript
复制
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}')

产出如下:

代码语言:javascript
复制
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,这是无用的。

我在文档中找不到一种既可以使用ORM,又可以显式地检查池中的连接的方法。

我有以下问题:

  1. await User.query.gino.all()从池中签出连接吗?它是怎么发布的?
  2. 如何在事务中包装查询?我感到不安的是,我无法明确地控制从池中获取连接的时间/位置,以及如何释放连接。

本质上,我希望test_engine_explicit()中的风格能够与Gino一起工作,但也许我只是不理解Gino是如何工作的。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-10-30 14:40:17

我以前从未使用过GINO,但是在快速查看代码之后:

  1. GINO连接简单的按如下方式执行提供的子句。因此,如果您提供裸露的User.select(),那么它不会增加任何内容。
  2. 如果您想实现与使用User.query.gino.all()相同的功能,但自己维护连接,则可以使用跟着医生,而不是普通的User.select()
代码语言:javascript
复制
async with engine.acquire() as conn:
    return await conn.all(User.query) 

刚刚测试过了,对我来说很好。

关于连接池,我不确定我是否正确地回答了这个问题,但是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.

GINO中也有一个人工事务控制,因此您可以手动创建不可重用、不可重用的连接和控制事务流:

代码语言:javascript
复制
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

至于连接发布,我找不到任何证据表明GINO释放了连接本身。我想这个池是由SQLAlchemy内核维护的。

我肯定没有直接回答你的问题,但希望它能对你有所帮助。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58617518

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档