Skip to main content

spanner-adbc

PyPI version Python versions Wheel License Build

A Python ADBC driver for Google Cloud Spanner.

Query Spanner through DBAPI 2.0 and fetch Apache Arrow results for pandas, Polars, DuckDB, or PyArrow.

Install

Requires Python 3.11 or later. Wheels bundle the native driver; see Supported platforms for OS requirements.

pip install "spanner-adbc[dbapi]"  # includes PyArrow and pandas

For the low-level ADBC API without DataFrame dependencies, install spanner-adbc. The Python import name is spanner_adbc.

Quickstart

This example assumes an existing Singers table with SingerId and FirstName columns.

import spanner_adbc.dbapi as spanner
from spanner_adbc import DatabaseOptions

with spanner.connect(
    db_kwargs={DatabaseOptions.URI.value: "spanner:///projects/my-project/instances/my-instance/databases/my-db"},
) as conn:
    with conn.cursor() as cur:
        cur.execute("SELECT SingerId, FirstName FROM Singers")
        df = cur.fetch_df()          # -> pandas.DataFrame

Use GoogleSQL @name parameters with cur.execute(...); ? placeholders are unsupported. fetchone() and fetchall() return Python rows; Arrow and DataFrame helpers are shown below.

Driver manifest (driver="spanner")

The package's spanner.connect() loads its bundled library directly. To use the generic adbc_driver_manager by driver name, install an ADBC driver manifest. Use a current driver manager; Python manifest support requires version 1.8.0 or later.

pip install --upgrade adbc-driver-manager
python -m spanner_adbc.manifest install

The equivalent console command is spanner-adbc-install-manifest.

import adbc_driver_manager.dbapi

with adbc_driver_manager.dbapi.connect(
    driver="spanner",
    uri="spanner:///projects/my-project/instances/my-instance/databases/my-db",
) as conn:
    ...

Current driver managers can also infer spanner from the URI scheme when driver is omitted.

  • Re-run the installer after upgrading, reinstalling, or moving the environment: the manifest contains the library's absolute path.
  • The default directory is <sys.prefix>/etc/adbc/drivers inside a virtual environment, or the platform's user configuration directory otherwise. python -m spanner_adbc.manifest path prints the target path.
  • Use install --dir /path/to/drivers for a custom directory on ADBC_DRIVER_PATH.
  • For a standalone shared library, edit the Driver.shared paths in the repository's spanner.toml.

Authentication

With no credential options, the driver uses Application Default Credentials: run gcloud auth application-default login locally, set GOOGLE_APPLICATION_CREDENTIALS, or use an attached service account on Google Cloud.

Pass explicit credentials in db_kwargs alongside DatabaseOptions.URI.value:

Option Value
DatabaseOptions.KEYFILE Credential JSON file path
DatabaseOptions.KEYFILE_JSON Credential JSON contents
DatabaseOptions.ACCESS_TOKEN OAuth bearer token; never refreshed
DatabaseOptions.IMPERSONATE_TARGET_PRINCIPAL Service account to impersonate using ADC or explicit base credentials

Use each enum member's .value as the key. ACCESS_TOKEN cannot be combined with key-file credentials or impersonation. See the option reference for scopes and other auth settings.

For the Spanner emulator, use anonymous mode:

import spanner_adbc.dbapi as spanner
from spanner_adbc import DatabaseOptions

with spanner.connect(db_kwargs={
    DatabaseOptions.URI.value: "spanner:///projects/p/instances/i/databases/d",
    DatabaseOptions.ENDPOINT.value: "localhost:9010",
    DatabaseOptions.EMULATOR.value: "true",
}) as conn:
    ...

Emulator mode rejects explicit credential options; ambient ADC is ignored.

Options

connect() argument Purpose
db_kwargs Database options, including the required uri
conn_kwargs Connection options
autocommit False by default; see Transactions

Use DatabaseOptions, ConnectionOptions, and StatementOptions enums, or raw option keys. The option reference lists types, defaults, and accepted values. Set cursor options with conn.cursor(adbc_stmt_kwargs={...}) or cur.adbc_statement.set_options(**{...}).

import spanner_adbc.dbapi as spanner
from spanner_adbc import ConnectionOptions, DatabaseOptions, StatementOptions

with spanner.connect(
    db_kwargs={DatabaseOptions.URI.value: "spanner:///projects/p/instances/i/databases/d"},
    conn_kwargs={ConnectionOptions.READ_STALENESS.value: "max:10s"},
    autocommit=True,  # bounded staleness on a single-use read
) as conn:
    with conn.cursor(
        adbc_stmt_kwargs={StatementOptions.ROWS_PER_BATCH.value: "1024"}
    ) as cur:
        cur.execute("SELECT * FROM Singers")

In manual query transactions, max:<duration> and min:<timestamp> bounds become exact staleness and a fixed read timestamp respectively. Set ConnectionOptions.READONLY.value to "true" to reject DML, DDL, and ingest; rollback remains available.

Transactions

DBAPI defaults to autocommit=False. A manual transaction accepts either queries or writes, chosen by its first query or write; mixing them raises adbc_driver_manager.ProgrammingError until commit or rollback. Queries share a snapshot. DML is buffered until conn.commit(), so queries cannot read buffered writes.

DDL always executes immediately: rollback cannot undo it, and it runs before buffered DML. Use autocommit=True for immediately committed DML, including THEN RETURN statements. See transactions for bulk-ingest and partitioned-DML behavior.

import spanner_adbc.dbapi as spanner
from adbc_driver_manager import ProgrammingError
from spanner_adbc import DatabaseOptions

with spanner.connect(
    db_kwargs={DatabaseOptions.URI.value: "spanner:///projects/my-project/instances/my-instance/databases/my-db"},
) as conn:
    with conn.cursor() as cur:
        # DDL applies immediately.
        cur.execute("DROP TABLE IF EXISTS Albums")
        cur.execute("CREATE TABLE Albums (Id INT64 NOT NULL) PRIMARY KEY (Id)")

        cur.execute("INSERT INTO Albums (Id) VALUES (1)")  # a DML transaction: buffered
        # Commit before querying the inserted row.
        try:
            cur.execute("SELECT COUNT(*) FROM Albums")
            raise AssertionError("expected the guarded query to raise")
        except ProgrammingError:
            pass
    conn.commit()

    with conn.cursor() as cur:
        cur.execute("SELECT COUNT(*) FROM Albums")
        assert cur.fetchone()[0] == 1
    conn.rollback()  # end the query snapshot

Working with DataFrames

The quickstart uses pandas. The examples below use the same Singers table with SingerId and FirstName columns. Install polars or duckdb separately for those examples.

pyarrow — results as a native Arrow table:

import spanner_adbc.dbapi as spanner
from spanner_adbc import DatabaseOptions

with spanner.connect(
    db_kwargs={DatabaseOptions.URI.value: "spanner:///projects/my-project/instances/my-instance/databases/my-db"},
) as conn:
    with conn.cursor() as cur:
        cur.execute("SELECT SingerId, FirstName FROM Singers ORDER BY SingerId")
        table = cur.fetch_arrow_table()      # -> pyarrow.Table

polars — read straight from the connection:

import polars as pl
import spanner_adbc.dbapi as spanner
from spanner_adbc import DatabaseOptions

with spanner.connect(
    db_kwargs={DatabaseOptions.URI.value: "spanner:///projects/my-project/instances/my-instance/databases/my-db"},
) as conn:
    df = pl.read_database(
        "SELECT SingerId, FirstName FROM Singers ORDER BY SingerId",
        connection=conn,                     # an ADBC connection, not a URI
    )

DuckDB — query the fetched Arrow table in-process:

import duckdb
import spanner_adbc.dbapi as spanner
from spanner_adbc import DatabaseOptions

with spanner.connect(
    db_kwargs={DatabaseOptions.URI.value: "spanner:///projects/my-project/instances/my-instance/databases/my-db"},
) as conn:
    with conn.cursor() as cur:
        cur.execute("SELECT SingerId, FirstName FROM Singers")
        singers = cur.fetch_arrow_table()

# DuckDB can query the Arrow table by variable name.
top = duckdb.sql("SELECT COUNT(*) AS n, MIN(FirstName) AS first FROM singers").fetchone()

Bulk insert a DataFrame

cur.adbc_ingest(table, data, mode=...) inserts Arrow-compatible data in bulk. Convert pandas DataFrames to Arrow as shown here:

import pandas as pd
import pyarrow as pa
import spanner_adbc.dbapi as spanner
from spanner_adbc import DatabaseOptions

frame = pd.DataFrame({"SingerId": [10, 11], "FirstName": ["Carol", "Dave"]})

with spanner.connect(
    db_kwargs={DatabaseOptions.URI.value: "spanner:///projects/my-project/instances/my-instance/databases/my-db"},
    autocommit=True,                         # apply immediately; returns the row count
) as conn:
    with conn.cursor() as cur:
        # `append` inserts into an existing table (the default mode is `create`).
        rows = cur.adbc_ingest("Singers", pa.Table.from_pandas(frame), mode="append")

The mode selects how the target table is handled:

  • create — create the table from the data's Arrow schema first, erroring if it already exists (the default).
  • append — insert into an existing table.
  • create_append — create the table only if it is absent, then insert.
  • replace — drop any existing table, recreate it from the schema, then insert.

Create modes omit a primary key, so Spanner supplies a hidden rowid column. For an explicit primary key, create the table with SQL first and use mode="append". In manual mode, inserts need conn.commit(); table creation or replacement still happens immediately. Autocommit loads may commit in multiple chunks, so a failed load can leave rows written.

Partitioned reads and Data Boost

A large scan can be split into independent partitions and read in parallel — optionally on Spanner's serverless Data Boost compute, so the work is isolated from your provisioned instance. This uses the ADBC partitioned-execution extension (adbc_execute_partitions / adbc_read_partition):

import spanner_adbc.dbapi as spanner
from spanner_adbc import DatabaseOptions, StatementOptions

with spanner.connect(
    db_kwargs={DatabaseOptions.URI.value: "spanner:///projects/my-project/instances/my-instance/databases/my-db"},
) as conn:
    with conn.cursor() as cur:
        # Optional statement options, set on the underlying ADBC statement:
        cur.adbc_statement.set_options(**{
            StatementOptions.DATA_BOOST.value: "true",  # run on Data Boost
        })
        partitions, schema = cur.adbc_execute_partitions("SELECT SingerId FROM Singers")

    # Each descriptor is opaque bytes; it can be shipped to another worker,
    # process, or connection and read independently.
    for token in partitions:
        with conn.cursor() as cur:
            cur.adbc_read_partition(token)
            table = cur.fetch_arrow_table()
            ...

Spanner decides partitionability from the query plan. Simple scans are suitable; joins, ordering, and aggregation can prevent partitioning. See the partitionability rules.

Descriptors contain SQL and transaction identifiers and are unauthenticated. Only read descriptors from trusted sources: they execute using the receiving connection's credentials.

Supported platforms

pip selects a wheel matching the OS and architecture:

Platform Wheel tag Minimum requirement
Linux x86-64 manylinux_2_35_x86_64 glibc >= 2.35
Linux aarch64 manylinux_2_35_aarch64 glibc >= 2.35
Linux x86-64 musl musllinux_1_2_x86_64 musl libc >= 1.2
Linux aarch64 musl musllinux_1_2_aarch64 musl libc >= 1.2
macOS arm64 macosx_11_0_arm64 macOS >= 11.0
macOS x86-64 macosx_10_15_x86_64 macOS >= 10.15
Windows x86-64 win_amd64 64-bit Windows
Windows arm64 win_arm64 ARM64 Windows

Building for an older OS requires a compatible native driver and Python dependencies. For local builds and releases, see CONTRIBUTING.md.

Metadata

Release files for spanner-adbc 0.8.0

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

Built distributions (wheels)

Table of built distributions (wheels) for spanner-adbc 0.8.0
File
spanner_adbc-0.8.0-py3-none-win_arm64.whl Python 3 none Windows ARM64 Details
spanner_adbc-0.8.0-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details
spanner_adbc-0.8.0-py3-none-musllinux_1_2_x86_64.whl Python 3 none Linux musl 1.2+ x86-64 Details
spanner_adbc-0.8.0-py3-none-musllinux_1_2_aarch64.whl Python 3 none Linux musl 1.2+ ARM64 Details
spanner_adbc-0.8.0-py3-none-manylinux_2_35_x86_64.whl Python 3 none Linux glibc 2.35+ x86-64 Details
spanner_adbc-0.8.0-py3-none-manylinux_2_35_aarch64.whl Python 3 none Linux glibc 2.35+ ARM64 Details
spanner_adbc-0.8.0-py3-none-macosx_11_0_arm64.whl Python 3 none macOS 11.0+ ARM64 Details
spanner_adbc-0.8.0-py3-none-macosx_10_15_x86_64.whl Python 3 none macOS 10.15+ x86-64 Details

Total release size: 51.9 MB

Release files / spanner_adbc-0.8.0-py3-none-win_arm64.whl

Download URL spanner_adbc-0.8.0-py3-none-win_arm64.whl
Size 6.6 MB
Tags Python 3 Windows ARM64
SHA-256 checksum
How to use checksums
a070e6a9b84e52ce190c10206687380ceb0c2d3f70e7fc570448ec7761b50946
BLAKE2b-256 checksum
How to use checksums
4f940177fefe079bb786ad35aabef95c7029864d0c2f51bb8689b50e977e7a00
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 Sep 18, 2026.

Transparency log

Release files / spanner_adbc-0.8.0-py3-none-win_amd64.whl

Download URL spanner_adbc-0.8.0-py3-none-win_amd64.whl
Size 7.0 MB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
d5576bad21380de97e0901bbca4bd9a6a662b88766971ab813d7475c92e9ebdc
BLAKE2b-256 checksum
How to use checksums
cb4c2864088715417d7af7fa46acf236e898caeb6f5c453d3abc1ce97087fdfb
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 Sep 18, 2026.

Transparency log

Release files / spanner_adbc-0.8.0-py3-none-musllinux_1_2_x86_64.whl

Download URL spanner_adbc-0.8.0-py3-none-musllinux_1_2_x86_64.whl
Size 6.7 MB
Tags Linux musl 1.2+ x86-64 Python 3
SHA-256 checksum
How to use checksums
323b457feaf03aaddb5b7d07660a05dcc69949abe7bffc8c721b3688656f2e7c
BLAKE2b-256 checksum
How to use checksums
b9b3722f46b23d724fc35bb1f903d1f10cdb0bfaa67cdc1058d926bc3252fbe3
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 Sep 18, 2026.

Transparency log

Release files / spanner_adbc-0.8.0-py3-none-musllinux_1_2_aarch64.whl

Download URL spanner_adbc-0.8.0-py3-none-musllinux_1_2_aarch64.whl
Size 6.3 MB
Tags Linux musl 1.2+ ARM64 Python 3
SHA-256 checksum
How to use checksums
09d14c508ce126ca364b701f23d05d769c032083becf058c0dd2f8c6ebe080be
BLAKE2b-256 checksum
How to use checksums
471738b2a071af2a677e79135e22d1c572147217fc4297132bf95d5d27c638bf
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 Sep 18, 2026.

Transparency log

Release files / spanner_adbc-0.8.0-py3-none-manylinux_2_35_x86_64.whl

Download URL spanner_adbc-0.8.0-py3-none-manylinux_2_35_x86_64.whl
Size 6.7 MB
Tags Linux glibc 2.35+ x86-64 Python 3
SHA-256 checksum
How to use checksums
b5b9ddc3d51fb06551c415b2192a3ece8ab01789032662218e25f45443f37186
BLAKE2b-256 checksum
How to use checksums
0d0a4b3daa1b5e9e1cc5be87a055b61cb4095b18ed63ce249640238f93c57cba
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 Sep 18, 2026.

Transparency log

Release files / spanner_adbc-0.8.0-py3-none-manylinux_2_35_aarch64.whl

Download URL spanner_adbc-0.8.0-py3-none-manylinux_2_35_aarch64.whl
Size 6.2 MB
Tags Linux glibc 2.35+ ARM64 Python 3
SHA-256 checksum
How to use checksums
a3a74aaaab478763b0f674e710e77ee5d34a0bd2bb39cdb15ebd7973c6bc0782
BLAKE2b-256 checksum
How to use checksums
2bcef123b9f982cf1eb417bcb5f41a47601c0db40005066bd0ac063c8a2d1534
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 Sep 18, 2026.

Transparency log

Release files / spanner_adbc-0.8.0-py3-none-macosx_11_0_arm64.whl

Download URL spanner_adbc-0.8.0-py3-none-macosx_11_0_arm64.whl
Size 6.0 MB
Tags Python 3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
f5088ff2c44d2b1498fd7362c0bab6e7e8c8a9c48be57a5b56369d4baf10ede2
BLAKE2b-256 checksum
How to use checksums
9e0ec68df767fff9c2b2aeccedd9f28d66b70885828cd09ef07b918a75517e0d
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 Sep 18, 2026.

Transparency log

Release files / spanner_adbc-0.8.0-py3-none-macosx_10_15_x86_64.whl

Download URL spanner_adbc-0.8.0-py3-none-macosx_10_15_x86_64.whl
Size 6.3 MB
Tags Python 3 macOS 10.15+ x86-64
SHA-256 checksum
How to use checksums
57e94b3df7ede6ff0f833026f9d86ea490449ff1dd0ae503f2b5b36af964fc28
BLAKE2b-256 checksum
How to use checksums
c3f04f0fc2b9b9875607b5c282b8b4982ee95d8d3fa40cf6cb2d14bb2c22dc65
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 Sep 18, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.8.0 This release

8 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