asyncpg Documentation

repository·master·Indexed 27 days ago

https://github.com/magicstack/asyncpg

A high-performance PostgreSQL database client library designed for Python's asyncio framework. It implements the PostgreSQL binary protocol natively to provide direct access to advanced features. Key functionality includes connection and pool management via Connection and Pool classes, high-performance bulk data operations using the COPY protocol, prepared statements, and a Cluster class for managing local PostgreSQL instances, including TempCluster and HotStandbyCluster.

Tokens
12.8K
Snippets
24
Records
88
Agent score
91%

What's inside asyncpg

  1. asyncpg Overview and Compatibility

    master

    asyncpg is a fast PostgreSQL database client library for Python/asyncio. It implements the PostgreSQL server protocol natively, providing direct access to features like prepared statements, scrollable cursors, and automatic encoding/decoding of composite types and arrays.

    Requirements:

    • Python: 3.9 or later
    • PostgreSQL: Versions 9.5 to 18 (other versions may work but are not actively tested)
  2. Manage transactions and nested transactions

    master

    The recommended way to use transactions is via an async with statement on a Connection.transaction() object.

    Nested Transactions: asyncpg supports nested transactions. When you create a nested transaction context, it automatically creates a PostgreSQL savepoint. If an exception occurs within the nested block, that specific savepoint is rolled back without affecting the outer transaction.

    async with connection.transaction():
        await connection.execute("INSERT INTO mytable VALUES(1, 2, 3)")
    
    # Nested transaction example
    async with connection.transaction():
        await connection.execute('CREATE TABLE mytab (a int)')
        try:
            async with connection.transaction():
                await connection.execute('INSERT INTO mytab (a) VALUES (1), (2)')
                raise Exception
        except:
            pass
        # The nested transaction was rolled back, but the outer one can continue
        assert await connection.fetch('SELECT a FROM mytab') == []
  3. Install asyncpg with GSSAPI/SSPI authentication support

    master

    To enable GSSAPI/SSPI authentication (SSPI on Windows and GSSAPI on non-Windows platforms), install the optional dependency using the [gssauth] extra.

    Linux Requirements: Installing GSSAPI on Linux requires a C compiler and Kerberos 5 development files. You can obtain these by installing:

    • libkrb5-dev on Debian/Ubuntu
    • krb5-devel on RHEL/Fedora

    Windows GSSAPI usage: Alternatively, you can use GSSAPI on Windows by:

    1. Running pip install gssapi.
    2. Installing Kerberos for Windows.
    3. Setting the gsslib parameter or the PGGSSLIB environment variable to gssapi when connecting.
    $ pip install 'asyncpg[gssauth]'
  4. Build asyncpg from source

    master

    To build asyncpg from a Git checkout, ensure you have:

    • Cloned the repository with --recurse-submodules.
    • A working C compiler.
    • CPython header files (e.g., python3-dev on Debian/Ubuntu or python3-devel on RHEL/Fedora).

    Run the following command in the root of the source checkout to install in editable mode:

    Debug Build: To create a debug build containing more runtime checks, set the ASYNCPG_DEBUG environment variable to 1 during installation.

  5. Install asyncpg

    master

    asyncpg is available on PyPI. It has no dependencies when not using GSSAPI/SSPI authentication.

    To install the standard version:

    pip install asyncpg

    To install with support for GSSAPI/SSPI authentication:

    pip install 'asyncpg[gssauth]'
    pip install asyncpg
  6. Establish a connection and run queries with asyncpg

    master

    To interact with a PostgreSQL database, use asyncpg.connect() to establish a new session. This returns a Connection instance used to execute statements and manage transactions.

    Note that asyncpg uses native PostgreSQL syntax for query arguments using $n (e.g., $1, $2).

    import asyncio
    import asyncpg
    import datetime
    
    async def main():
        # Establish a connection to an existing database
        conn = await asyncpg.connect('postgresql://postgres@localhost/test')
        
        # Execute a statement to create a new table.
        await conn.execute('''
            CREATE TABLE users(
                id serial PRIMARY KEY,
                name text,
                dob date
            )
        ''')
    
        # Insert a record using $n positional arguments
        await conn.execute('''
            INSERT INTO users(name, dob) VALUES($1, $2)
        ''', 'Bob', datetime.date(1984, 3, 1))
    
        # Select a single row
        row = await conn.fetchrow(
            'SELECT * FROM users WHERE name = $1', 'Bob')
        # row is an asyncpg.Record
    
        # Close the connection.
        await conn.close()
    
    asyncio.run(main())
  7. Manage database connections with asyncpg.create_pool()

    master

    For server-side applications handling frequent requests, use asyncpg.create_pool() to create a Pool object. This provides an advanced connection pooling implementation that eliminates the need for external poolers like PgBouncer.

    To use a connection from the pool, use pool.acquire() within an async with block.

    import asyncio
    import asyncpg
    from aiohttp import web
    
    async def handle(request):
        """Handle incoming requests."""
        pool = request.app['pool']
        power = int(request.match_info.get('power', 10))
    
        # Take a connection from the pool.
        async with pool.acquire() as connection:
            # Open a transaction.
            async with connection.transaction():
                # Run the query passing the request argument.
                result = await connection.fetchval('select 2 ^ $1', power)
                return web.Response(
                    text="2 ^ {} is {}".format(power, result))
    
    async def init_db(app):
        """Initialize a connection pool."""
         app['pool'] = await asyncpg.create_pool(database='postgres',
                                                     user='postgres')
         yield
         await app['pool'].close()
    
    # ... (rest of the aiohttp setup) ...
  8. Iterate over large result sets using Cursors

    master

    Cursors allow you to iterate over large query results without fetching all rows into memory at once.

    Important Requirements:

    1. Transactions: Cursors created via Connection.cursor() or PreparedStatement.cursor() must be used within a transaction block. Attempting to use them outside a transaction will raise asyncpg.exceptions.InterfaceError.
    2. Direction: Cursors provided by asyncpg are non-scrollable (forward-only). To use scrollable cursors, you must execute DECLARE ... SCROLL CURSOR directly via SQL.

    Usage Patterns:

    • Asynchronous Iteration: Use async for with con.cursor(query) for efficient prefetching.
    • Manual Navigation: Use cur.forward(n), cur.fetchrow(), or cur.fetch(n) to move through the result set manually.
    async def iterate(con: Connection):
        async with con.transaction():
            # Efficient prefetching via async for
            async for record in con.cursor('SELECT generate_series(0, 100)'):
                print(record)
    
    async def manual_iterate(con: Connection):
        async with con.transaction():
            cur = await con.cursor('SELECT generate_series(0, 100)')
            await cur.forward(10)
            print(await cur.fetchrow())
            print(await cur.fetch(5))
  9. Create a connection pool with create_pool()

    master

    Use asyncpg.create_pool() to manage a set of connections. It is recommended to use it within an async with block to ensure the pool is closed properly.

    Key parameters:

    • dsn: Connection string.
    • min_size: Minimum number of connections to keep in the pool (default: 10).
    • max_size: Maximum number of connections in the pool (default: 10).
    • max_queries: Maximum number of queries a connection can execute before being closed and replaced (default: 50000).
    • max_inactive_connection_lifetime: Maximum time (in seconds) a connection can be idle before being closed (default: 300.0).
    • setup: An async function called for each connection after it is created.
    • init: An async function called for each connection after it is created but before it is used.
    • reset: An async function called for each connection when it is released back to the pool.
    async with asyncpg.create_pool(user='postgres',
                                   command_timeout=60) as pool:
        await pool.fetch('SELECT 1')