diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2022-11-23 13:08:59 -0500 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2022-11-23 13:11:26 -0500 |
| commit | 1c9aa8c046638f90deeadee4d5492c9b6e19f6b2 (patch) | |
| tree | 402f504711bc2a7979f16809a8d17420372ad5e9 | |
| parent | 3b6a5fb05c7bb6976cc523df5b83824ab6ae07aa (diff) | |
| download | sqlalchemy-1c9aa8c046638f90deeadee4d5492c9b6e19f6b2.tar.gz | |
improve docs for event listening with asyncio
add examples, including how to listen on an async_sessionmaker
Change-Id: I1d68324458c23bc830508c8ebfd3224d434c16a5
| -rw-r--r-- | doc/build/orm/extensions/asyncio.rst | 100 |
1 files changed, 88 insertions, 12 deletions
diff --git a/doc/build/orm/extensions/asyncio.rst b/doc/build/orm/extensions/asyncio.rst index d32af2415..102c65056 100644 --- a/doc/build/orm/extensions/asyncio.rst +++ b/doc/build/orm/extensions/asyncio.rst @@ -506,6 +506,11 @@ asyncio-facing APIs: :class:`_asyncio.AsyncSession` class, use the :class:`_orm.Session` class as the target. +* To register at the :class:`_orm.sessionmaker` level, combine an explicit + :class:`_orm.sessionmaker` with an :class:`_asyncio.async_sessionmaker` + using :paramref:`_asyncio.async_sessionmaker.sync_session_class`, and + associate events with the :class:`_orm.sessionmaker`. + When working within an event handler that is within an asyncio context, objects like the :class:`_engine.Connection` continue to work in their usual "synchronous" way without requiring ``await`` or ``async`` usage; when messages @@ -515,17 +520,24 @@ are passed a DBAPI level connection, such as :meth:`_events.PoolEvents.connect`, the object is a :term:`pep-249` compliant "connection" object which will adapt sync-style calls into the asyncio driver. +Examples of Event Listeners with Async Engines / Sessions / Sessionmakers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Some examples of sync style event handlers associated with async-facing API -constructs are illustrated below:: +constructs are illustrated below: + +* **Core Events on AsyncEngine** + + In this example, we access the :attr:`_asyncio.AsyncEngine.sync_engine` + attribute of :class:`_asyncio.AsyncEngine` as the target for + :class:`.ConnectionEvents` and :class:`.PoolEvents`:: import asyncio - from sqlalchemy import event, text + from sqlalchemy import event + from sqlalchemy import text from sqlalchemy.engine import Engine - from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine - from sqlalchemy.orm import Session - - ## Core events ## + from sqlalchemy.ext.asyncio import create_async_engine engine = create_async_engine("postgresql+asyncpg://scott:tiger@localhost:5432/test") @@ -553,7 +565,37 @@ constructs are illustrated below:: print("before execute!") - ## ORM events ## + async def go(): + async with engine.connect() as conn: + await conn.execute(text("select 1")) + await engine.dispose() + + + asyncio.run(go()) + + Output: + + .. sourcecode:: text + + New DBAPI connection: <AdaptedConnection <asyncpg.connection.Connection object at 0x7f33f9b16960>> + execute from event + before execute! + + +* **ORM Events on AsyncSession** + + In this example, we access :attr:`_asyncio.AsyncSession.sync_session` as the + target for :class:`_orm.SessionEvents`:: + + import asyncio + + from sqlalchemy import event + from sqlalchemy import text + from sqlalchemy.ext.asyncio import AsyncSession + from sqlalchemy.ext.asyncio import create_async_engine + from sqlalchemy.orm import Session + + engine = create_async_engine("postgresql+asyncpg://scott:tiger@localhost:5432/test") session = AsyncSession(engine) @@ -587,17 +629,51 @@ constructs are illustrated below:: asyncio.run(go()) -The above example prints something along the lines of: + Output: -.. sourcecode:: text + .. sourcecode:: text - New DBAPI connection: <AdaptedConnection <asyncpg.connection.Connection ...>> - execute from event - before execute! before commit! execute from event after commit! + +* **ORM Events on async_sessionmaker** + + For this use case, we make a :class:`_orm.sessionmaker` as the event target, + then assign it to the :class:`_asyncio.async_sessionmaker` using + the :paramref:`_asyncio.async_sessionmaker.sync_session_class` parameter:: + + import asyncio + + from sqlalchemy import event + from sqlalchemy.ext.asyncio import async_sessionmaker + from sqlalchemy.orm import sessionmaker + + sync_maker = sessionmaker() + maker = async_sessionmaker(sync_session_class=sync_maker) + + + @event.listens_for(sync_maker, "before_commit") + def before_commit(session): + print("before commit") + + + async def main(): + async_session = maker() + + await async_session.commit() + + + asyncio.run(main()) + + Output: + + .. sourcecode:: text + + before commit + + .. topic:: asyncio and events, two opposites SQLAlchemy events by their nature take place within the **interior** of a |
