Skip to main content

aiosql - Simple SQL in Python (aka YeSQL for Python)

SQL is code. Write it, version control it, comment it, and run it using files. Writing your SQL code in Python programs as strings doesn’t allow you to easily reuse them in SQL GUIs or CLI tools like psql. With aiosql you can organize your SQL statements in .sql files, load them into your python application as methods to call without losing the ability to use them as you would any other SQL file.

This project supports standard PEP 249 and asyncio based drivers for SQLite (sqlite3, aiosqlite, apsw), PostgreSQL (psycopg (3), apsycopg (3), psycopg2, pg8000, pygresql, asyncpg), MySQL (PyMySQL, mysqlclient, mysql-connector, asyncmy with this adapter), MariaDB (mariadb), DuckDB (duckdb) and MS SQL Server (pymssql), However, some detailed feature support may vary depending on the underlying driver and database engine actual capabilities.

Other SQL database drivers which support the pyformat or named PEP 249 paramstyles should work as well by just passing the driver as a parameter when building queries. Thus Oracle Database (oracledb) or Snowflake (snowflake.connector) should work out of the box… Please report with an issue if it actually works for you! Otherwise, extensions to support other database drivers can be written by you! See: Database Driver Adapters. Feel free to pull request!

This module is an implementation of Kris Jenkins’ yesql Clojure library to the Python ecosystem.

Badges

Build status Code Coverage Tests Issues Contributors Pypi Downloads Stars Version Code Size Databases Drivers Language Count Top Language Python Versions Badges BSD 2-Clause License

Usage

Install from pypi, for instance by running pip install aiosql.

Then write parametric SQL queries in a file and execute it from Python methods, eg this greetings.sql file:

-- name: get_all_greetings()
-- Get all the greetings in the database
select greeting_id, greeting
  from greetings
 order by 1;

-- name: get_user_by_username(username)^
-- Get a user from the database using a named parameter
select user_id, username, name
  from users
  where username = :username;

This example has an imaginary SQLite database with greetings and users. It prints greetings in various languages to the user and showcases the basic feature of being able to load queries from a SQL file and call them by name in python code. Query parameter declarations (eg (username)) are optional, and enforced when provided.

You can use aiosql to load the queries in this file for use in your Python application:

import aiosql
import sqlite3

queries = aiosql.from_path("greetings.sql", "sqlite3")

with sqlite3.connect("greetings.db") as conn:
    user = queries.get_user_by_username(conn, username="willvaughn")
    # user: (1, "willvaughn", "William")

    for _, greeting in queries.get_all_greetings(conn):
        # scan: (1, "Hi"), (2, "Aloha"), (3, "Hola"), …
        print(f"{greeting}, {user[2]}!")
    # Hi, William!
    # Aloha, William!
    # …

Or even in an asynchronous way, with two SQL queries running in parallel using aiosqlite and asyncio:

import asyncio
import aiosql
import aiosqlite

queries = aiosql.from_path("greetings.sql", "aiosqlite")

async def main():
    async with aiosqlite.connect("greetings.db") as conn:
        user = await queries.get_user_by_username(conn, username="willvaughn")

        async for _, greeting in queries.get_all_greetings(conn):
            print(f"{greeting}, {user[2]}!")

asyncio.run(main())

It may seem inconvenient to provide a connection on each call. You may have a look at the AnoDB DB class which wraps both a database connection and queries in one connection-like extended object, including performing automatic reconnection when needed. The wrapper also allows to cache query results.

Why you might want to use this

  • You think SQL is pretty good, and writing SQL is an important part of your applications.

  • You don’t want to write your SQL in strings intermixed with your python code.

  • You’re not using an ORM like SQLAlchemy or Django , with large (100k lines) code imprints vs under 1000 for aiosql and about 300 for anodb, and you don’t need to or don’t want to write SQL-like code with a Python syntax.

  • You want to be able to reuse your SQL in other contexts, eg loading it into psql or other database tools.

Why you might NOT want to use this

  • You’re looking for an ORM.

  • You aren’t comfortable writing SQL code.

  • You don’t have anything in your application that requires complicated SQL beyond basic CRUD operations.

  • Dynamically loaded objects built at runtime really bother you.

Metadata

Release files for aiosql 16.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for aiosql 16.0
File Size Uploaded Provenance Actions
aiosql-16.0.tar.gz 77.8 kB Without provenance Details for aiosql-16.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for aiosql 16.0
File Interpreter ABI Platform Actions
aiosql-16.0-py3-none-any.whl Python 3 none any Details for aiosql-16.0-py3-none-any.whl

Total release size: 104.0 kB

Release files / aiosql-16.0.tar.gz

Download URL aiosql-16.0.tar.gz
Size 77.8 kB
Tags Source
SHA-256 checksum
How to use checksums
0b14bb5875d426bc6d0941f36a093641e3a56ddd55d9063ea30040c3ee1d1088
BLAKE2b-256 checksum
How to use checksums
96dc019f0d89359e50427691be39e25af02bddad25ae83184215e2eb6dbc3764
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / aiosql-16.0-py3-none-any.whl

Download URL aiosql-16.0-py3-none-any.whl
Size 26.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9ba9b7ef69f125bfa562aa0b24891841af0ad2de8558b654a2b2a21d3b4a33a4
BLAKE2b-256 checksum
How to use checksums
68e4a00d23371f23c0c0516fe43e9adc3e2e5434f73a8050ad9f2584ef9ab8d7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Security for aiosql 16.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

16.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page