python Comment faire pour que SQLAlchemy dans Tornado soit asynchrone?





2 Answers

J'ai eu ce même problème dans le passé et je ne pouvais pas trouver une bibliothèque Async-MySQL fiable. Cependant, il existe une solution cool en utilisant Asyncio + Postgres . Vous avez juste besoin d'utiliser la bibliothèque aiopg , qui vient avec le support SQLAlchemy aiopg à l'emploi:

import asyncio
from aiopg.sa import create_engine
import sqlalchemy as sa


metadata = sa.MetaData()

tbl = sa.Table('tbl', metadata,
           sa.Column('id', sa.Integer, primary_key=True),
           sa.Column('val', sa.String(255)))

@asyncio.coroutine
def go():
    engine = yield from create_engine(user='aiopg',
                                      database='aiopg',
                                      host='127.0.0.1',
                                      password='passwd')

    with (yield from engine) as conn:
        yield from conn.execute(tbl.insert().values(val='abc'))

        res = yield from conn.execute(tbl.select().where(tbl.c.val=='abc'))
        for row in res:
            print(row.id, row.val)


loop = asyncio.get_event_loop()
loop.run_until_complete(go())
python python-2.7 sqlalchemy tornado

Comment faire pour que SQLAlchemy dans Tornado soit async ? J'ai trouvé un exemple pour MongoDB sur un exemple async mongo mais je n'ai pas trouvé de motor pour SQLAlchemy . Est-ce que quelqu'un sait comment faire des requêtes SQLAlchemy à exécuter avec tornado.gen (J'utilise MySQL ci-dessous SQLAlchemy , au moment où mes gestionnaires lit à partir de la base de données et le résultat de retour, je voudrais faire async).




Pas de tornade, mais nous avons en quelque sorte fait de SQLAlchemy async en asyncio dans le projet GINO :

import asyncio
from gino import Gino, enable_task_local
from sqlalchemy import Column, Integer, Unicode, cast

db = Gino()


class User(db.Model):
    __tablename__ = 'users'

    id = Column(Integer(), primary_key=True)
    nickname = Column(Unicode(), default='noname')


async def main():
    await db.create_pool('postgresql://localhost/gino')

    # Create object, `id` is assigned by database
    u1 = await User.create(nickname='fantix')
    print(u1.id, u1.nickname)  # 1 fantix

    # Retrieve the same row, as a different object
    u2 = await User.get(u1.id)
    print(u2.nickname)  # fantix

    # Update affects only database row and the operating object
    await u2.update(nickname='daisy')
    print(u2.nickname)  # daisy
    print(u1.nickname)  # fantix

    # Returns all user objects with "d" in their nicknames
    users = await User.query.where(User.nickname.contains('d')).gino.all()

    # Find one user object, None if not found
    user = await User.query.where(User.nickname == 'daisy').gino.first()

    # Execute complex statement and return command status
    status = await User.update.values(
        nickname='No.' + cast(User.id, Unicode),
    ).where(
        User.id > 10,
    ).gino.status()

    # Iterate over the results of a large query in a transaction as required
    async with db.transaction():
        async for u in User.query.order_by(User.id).gino.iterate():
            print(u.id, u.nickname)


loop = asyncio.get_event_loop()
enable_task_local(loop)
loop.run_until_complete(main())

Il ressemble un peu, mais en fait assez différent de SQLAlchemy ORM. Parce que nous n'avons utilisé qu'une partie du noyau de SQLAlchemy et construit un simple ORM au-dessus. Il utilise asyncpg dessous, donc c'est seulement pour PostgreSQL .

Mise à jour : GINO soutient maintenant Tornado, grâce à la contribution de Vladimir Goncharov. Voir les documents ici






Related