Registry / gcp / sqlalchemy-spanner

sqlalchemy-spanner

JSON →
library1.20.0pypypi✓ verified 8d ago

sqlalchemy-spanner is a Python SQLAlchemy dialect that enables applications to connect to and interact with Google Cloud Spanner databases. It leverages Cloud Spanner's scale, strong consistency, and high availability. The library is actively maintained by Google and sees regular releases with new features and bug fixes.

pip install sqlalchemy-spanner
INSTALL
IMPORT
SIG · SQLALCHEMY-SPANNER
S
sqlalchemy-spanner
gcppythonv1.20.0
Install
9.3s avg
Import
657ms
Disk
113MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.93.13
musl
3.93.13
Install & Compatibility
Where this runs
tested against v1.20.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
py 3.103.95 runs
installs and imports cleanly · install 0.0s · import 0.704s · 113.5MB
glibc
py 3.103.95 runs
installs and imports cleanly · install 9.3s · import 0.610s · 109MB
113MB installed
● package 113MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

create_engine
from sqlalchemy import create_engine
The Spanner dialect is typically loaded via the connection string, not direct import of a dialect class.

This quickstart demonstrates how to establish a connection to a Google Cloud Spanner database, define a table, insert data, and query it using the SQLAlchemy ORM. Ensure you have a GCP project, Spanner instance, and database set up, and that your application has appropriate authentication (e.g., via `GOOGLE_APPLICATION_CREDENTIALS`). The example shows direct DDL for table creation, as DDL is not transactional in Spanner.

import os from sqlalchemy import create_engine, text, MetaData, Table, Column, String, Integer # Set these environment variables or replace directly project_id = os.environ.get('SPANNER_PROJECT_ID', 'your-gcp-project-id') instance_id = os.environ.get('SPANNER_INSTANCE_ID', 'your-spanner-instance-id') database_id = os.environ.get('SPANNER_DATABASE_ID', 'your-spanner-database-id') # For SQLAlchemy 1.4+ and 2.0, use 'spanner+spanner:///' # For SQLAlchemy 1.3, use 'spanner:///' db_url = f"spanner+spanner:///projects/{project_id}/instances/{instance_id}/databases/{database_id}" try: engine = create_engine(db_url) # Example: Define a table for demonstration metadata = MetaData() users = Table( 'users', metadata, Column('user_id', String(36), primary_key=True), Column('name', String(255), nullable=False), Column('age', Integer) ) # Create tables (DDL operations are not transactional in Spanner) with engine.connect() as connection: connection.execute(text("CREATE TABLE IF NOT EXISTS users (user_id STRING(36) NOT NULL, name STRING(255) NOT NULL, age INT64) PRIMARY KEY (user_id)")) connection.commit() print("Table 'users' ensured.") # Insert data with engine.begin() as connection: connection.execute(users.insert(), {"user_id": "user1", "name": "Alice", "age": 30}) connection.execute(users.insert(), {"user_id": "user2", "name": "Bob", "age": 24}) print("Data inserted.") # Query data with engine.connect() as connection: result = connection.execute(users.select().where(users.c.age > 25)).fetchall() print("Users older than 25:", result) except Exception as e: print(f"An error occurred: {e}") print("Ensure Cloud Spanner project, instance, and database are correctly configured and `GOOGLE_APPLICATION_CREDENTIALS` is set or default credentials are available.")
Debug
Known issues
gotchaThe database URL format for `sqlalchemy-spanner` differs between SQLAlchemy 1.3 and 1.4+/2.0. For SQLAlchemy 1.3, use `spanner:///...`. For SQLAlchemy 1.4+ and 2.0, use `spanner+spanner:///...`.
fix
Adjust the connection string based on your SQLAlchemy version. E.g., `create_engine("spanner+spanner:///projects/...")` for newer SQLAlchemy versions.
affects: <1.4.0 (for older URL style)
gotchaCloud Spanner does not support DDL (Data Definition Language) statements within transactions. Any DDL operations performed will not be rolled back upon transaction failure.
fix
Be mindful that DDL statements are implicitly committed and irreversible in the context of a transaction. Consider using `connection.execute(text('DDL_STATEMENT'))` followed by `connection.commit()` outside of explicit transaction blocks for DDL.
affects: All
gotchaThe dialect and the underlying DB API driver do not support Spanner mutations directly; only DML (Data Manipulation Language) statements are supported for updates.
fix
Utilize SQLAlchemy's ORM or Core DML statements (INSERT, UPDATE, DELETE) which are translated into Spanner-compatible DML.
affects: All
gotchaWhen using Alembic for migrations, setting `version_table_pk` to `False` in your Alembic environment configuration is highly recommended to avoid issues with Spanner's primary key restrictions on the `alembic_versions` table.
fix
In your `env.py` or Alembic configuration, ensure `version_table_pk = False` for Spanner migrations.
affects: All
gotchaThe `sqlalchemy-spanner` dialect is currently synchronous only. There is no official asynchronous dialect available, which can be a blocker for projects requiring an async engine with SQLAlchemy 2.0+'s async features.
fix
Consider using thread pools or synchronous execution within an async application, or explore third-party async wrappers. A native async SpannerSessionService is a feature request for the underlying `google-cloud-spanner` client.
affects: All
gotchaUsing `autoload=True` with `MetaData` in a highly concurrent environment can lead to `sqlalchemy.exc.CompileError: Unconsumed column names` due to race conditions during table reflection. It's an anti-pattern to reflect tables on every statement.
fix
Reflect all necessary `Table` objects upfront, once, before your program begins processing requests, rather than dynamically reflecting them within hot code paths.
affects: All
gotchaThe dialect does not currently propagate the `timeout` execution option to the underlying gRPC client, causing all queries to use the default gRPC timeout of 3600 seconds regardless of `execution_options(timeout=...)`.
fix
Be aware of the default long timeout. For specific timeout control, you may need to apply it at the underlying `google-cloud-spanner` client level if direct access is available, or await a future update to the dialect.
affects: All current versions (as of 1.17.3)
breakingThe `sqlalchemy-spanner` dialect relies on Google Cloud Application Default Credentials (ADC) or explicit credentials (e.g., via `GOOGLE_APPLICATION_CREDENTIALS`) to authenticate with Spanner. Without proper authentication, connection attempts will fail.
fix
Set up Application Default Credentials (ADC) in your environment (e.g., `gcloud auth application-default login` if using the gcloud CLI) or ensure the `GOOGLE_APPLICATION_CREDENTIALS` environment variable points to a valid service account key file. Consult Google Cloud's authentication documentation for detailed setup instructions: https://cloud.google.com/docs/authentication/external/set-up-adc
affects: All
gotchaThe `sqlalchemy-spanner` dialect, like all Google Cloud client libraries, requires Application Default Credentials (ADC) to authenticate. If not configured, you will encounter 'Your default credentials were not found' errors.
fix
Ensure Application Default Credentials are set up in your environment. Refer to `https://cloud.google.com/docs/authentication/external/set-up-adc` for guidance. This typically involves setting the `GOOGLE_APPLICATION_CREDENTIALS` environment variable to the path of a service account key file or authenticating via `gcloud auth application-default login`.
affects: All
Errors
Common errors & fixes
sqlalchemy.exc.NoSuchModuleError: Can't load plugin: sqlalchemy.dialects:spanner
The `sqlalchemy-spanner` package is not installed or not accessible in the current Python environment, preventing SQLAlchemy from finding the 'spanner' dialect.
fix
pip install sqlalchemy-spanner
sqlalchemy.exc.OperationalError: (google.api_core.exceptions.NotFound: 404 Not found: projects/PROJECT_ID/instances/INSTANCE_ID/databases/DATABASE_ID)
The Spanner project, instance, or database specified in the connection string does not exist, or the authenticated service account/user lacks the necessary IAM permissions to access it.
fix
Verify the project ID, instance ID, and database name in your connection string are correct, and ensure the authenticated user or service account has appropriate IAM roles (e.g., `roles/spanner.databaseUser`) for the Spanner resource.
sqlalchemy.exc.CompileError: Spanner does not support auto-incrementing primary keys.
Cloud Spanner does not natively support auto-incrementing integer primary keys, and the `sqlalchemy-spanner` dialect prevents their definition in SQLAlchemy models.
fix
Remove `autoincrement=True` from primary key column definitions; instead, generate unique primary key values client-side (e.g., using UUIDs) before insertion, or configure Spanner's `GENERATE AS ROW ID` for `BYTES(16)` primary keys.
sqlalchemy.exc.CompileError: Spanner does not support the RETURNING clause.
The `sqlalchemy-spanner` dialect does not support the `RETURNING` clause in `INSERT` or `UPDATE` statements, as Cloud Spanner DML does not provide immediate return of affected rows or generated values.
fix
Remove the `.returning()` clause from your SQLAlchemy `insert()` or `update()` statements. If you need generated IDs, generate them client-side before insertion or query the table separately afterward.
Upgrade
Version history
1.20.0latest on PyPI · released Aug 25, 2026
Audit
Dependencies
SQLAlchemyrequiredThis package provides a dialect for SQLAlchemy, requiring SQLAlchemy itself. Compatible with SQLAlchemy 1.x (>=1.1.13) and 2.0.
google-cloud-spannerrequiredThe dialect is built on top of the Google Cloud Spanner DB API (PEP-249 compliant).
AlembicoptionalRecommended for database migrations with SQLAlchemy and Spanner.
Agent activity
29 hits · last 30 days
node
24
Meta
1
Resources
sqlalchemy-spanner — pip install sqlalchemy-spanner · libregistry