Skip to main content

Cassandra AsyncIO Driver

Wrapper for cassandra-driver that makes blocking calls awaitable using asyncio

Requires Python 3.10+ and Apache Cassandra Python Driver 3.30.1+ (3.x).

Installation

$ pip install cassandra-asyncio-driver

Usage

To adapt existing code to use the asyncio driver, replace:

from cassandra.cluster import Cluster

with:

from cassandra_asyncio.cluster import Cluster

Queries can be executed asynchronously using await session.aexecute().

For synchronous queries, session.execute() can still be used as normal.

aexecute() accepts the same arguments as execute_async() and returns the AsyncResultSet, preserving upstream column metadata, paging state, and current_rows. Use async for row in rows for automatic nonblocking paging, await rows.aall() to collect rows, or await rows.afetch_next_page() for manual paging. Ordinary for, list(rows), rows.all(), and rows.fetch_next_page() retain upstream synchronous behavior and may block while fetching pages. Use one consumer at a time and avoid mixing synchronous and async consumption of a result. Partial async consumption resumes at the next row when the iterator is closed; exhausted async results stay exhausted. Use await iterator.aclose() when explicitly ending an iterator early.

await session.aexecute_graph(...) wraps upstream execute_graph_async() for DSE Graph queries and returns the same async result interface. Continuous graph paging uses worker threads to consume upstream's blocking generator.

Use await session.aexecute_concurrent() to execute multiple statements with bounded concurrency. It accepts the same arguments as upstream execute_concurrent_async() and returns its ordered list of ExecutionResult(success, result_or_exc) entries. By default, raise_on_first_error=False, so inspect each entry for errors; pass True to raise an execution error instead. Successful entries contain AsyncResultSet objects with the same async iteration interface.

prepared = session.prepare("SELECT * FROM movies_to_watch WHERE genre = ?")
results = await session.aexecute_concurrent(
    [(prepared, ["Action"]), (prepared, ["Black Comedy"])],
    concurrency=2,
    raise_on_first_error=True,
)
for success, rows in results:
    async for row in rows:
        print(row)

Cancelling aexecute_concurrent() stops waiting, while submitted queries continue running and the upstream future remains active. Empty input returns []; concurrency must be a positive integer. Upstream submission runs in a worker thread because it can block even though the upstream method is named async.

Connecting, preparing statements, and shutting down remain synchronous driver operations. Cancelling an await does not cancel the query on the server. Always shut down the cluster when finished, for example with with Cluster(...).

All other Cassandra classes should continue to be imported from the usual paths.

For example:

import csv
import asyncio
from cassandra_asyncio.cluster import Cluster
from cassandra.auth import PlainTextAuthProvider
from cassandra.query import dict_factory


async def main():
    with open("movies.csv", "w", newline="") as output_file:
        # Prepare CSV writer
        fieldnames = ["genre", "name", "rating", "seen"]
        writer = csv.DictWriter(output_file, fieldnames=fieldnames, dialect="excel")
        writer.writeheader()

        # Connect to Cassandra using `cassandra_asyncio.cluster.Cluster`
        auth_provider = PlainTextAuthProvider(
            username="cassandra", password="cassandra"
        )
        with Cluster(auth_provider=auth_provider) as cluster:
            session = cluster.connect("lists")
            session.row_factory = dict_factory

            # Execute query asynchronously using `session.aexecute()`
            rows = await session.aexecute(
                "SELECT genre, name, rating, seen FROM movies_to_watch"
            )

            # Write rows to output file
            async for row in rows:
                writer.writerow(row)


if __name__ == "__main__":
    asyncio.run(main())

Development

Install PDM and use Python 3.10 or newer:

pdm sync -G test -G lint
pdm run lint       # Ruff lint checks and formatting checks
pdm run format     # Apply safe lint fixes and formatting
pdm run test       # Unit tests; no Cassandra server needed
pdm run check      # Lint, formatting, and unit tests together

CI runs these checks on Python 3.10 through 3.14 before building the package. Generated version files are excluded from Ruff.

Integration tests with Docker

With Docker installed and running, start a disposable instance using the official Cassandra image. Port 9042 must be available on the host. Run the tests from your host, in the project directory.

docker volume create cassandra-asyncio-data
docker run -d \
    --name cassandra-asyncio-tests \
    -v cassandra-asyncio-data:/var/lib/cassandra \
    --env MAX_HEAP_SIZE=1G \
    --env HEAP_NEWSIZE=256M \
    -p 127.0.0.1:9042:9042 \
    cassandra:5.0.9

Startup can take a few minutes. Wait until Cassandra accepts CQL queries:

until docker exec cassandra-asyncio-tests \
    cqlsh -e 'SELECT release_version FROM system.local;' >/dev/null 2>&1; do
    sleep 5
done

If it keeps waiting, press Ctrl+C and inspect docker logs cassandra-asyncio-tests. Allow Docker enough memory for Cassandra and its JVM (at least 2 GB).

Create the keyspace, then run the integration tests:

docker exec -i cassandra-asyncio-tests cqlsh <<'CQL'
CREATE KEYSPACE IF NOT EXISTS lists
WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1};
CQL

pdm sync -G test -G lint
pdm run test-integration

The image's default configuration disables authentication. The tests supply cassandra / cassandra credentials, which are ignored in this configuration; the driver may log a warning about it. For an existing local server with password authentication enabled, those credentials must be valid.

These tests create, truncate, and drop the lists.movies_to_watch table; use a disposable development database and run the whole file in order.

When finished, remove the container and its anonymous data volume:

docker rm --force --volumes cassandra-asyncio-tests

Metadata

Release files for cassandra-asyncio-driver 1.0.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 cassandra-asyncio-driver 1.0.0
File Size Uploaded
cassandra_asyncio_driver-1.0.0.tar.gz 12.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for cassandra-asyncio-driver 1.0.0
File Interpreter ABI Platform
cassandra_asyncio_driver-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 20.4 kB

Release files / cassandra_asyncio_driver-1.0.0.tar.gz

Download URL cassandra_asyncio_driver-1.0.0.tar.gz
Size 12.9 kB
Tags Source
SHA-256 checksum
How to use checksums
db149f50ade6e54c0f84f0e1bfe47680a7ecf7f366d16ac2e7c0cd951d0d19b3
BLAKE2b-256 checksum
How to use checksums
0091c6be2ddc5234d0ce95c336c9961d8af9ce372e37a91abe6de81c9a3070ea
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.

Transparency log

Release files / cassandra_asyncio_driver-1.0.0-py3-none-any.whl

Download URL cassandra_asyncio_driver-1.0.0-py3-none-any.whl
Size 7.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
eeabd25c691bf7893aefa3b3235d122bcc4c42a4d0c4a1d2a69a1b56b14fb432
BLAKE2b-256 checksum
How to use checksums
a3126361d1211795186f5a44d7d4df6c99bcbb8e467159f4c170ca28bfc73d46
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.

Transparency log

Release history Release notifications | RSS feed

1.0.1

2 release files

This release

1.0.0 This release

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

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