duckdb-python 1.5.4
DuckDB Python client providing in-process analytical SQL database with zero-config deployment. Runs entirely in-process (no server), supports pandas, PyArrow, Polars, and NumPy natively.
Overview
DuckDB is a columnar OLAP engine that runs inside the Python process. Two main API styles:
- Connection/DB-API 2.0 —
duckdb.connect(), conn.execute(), fetchall() — standard cursor interface
- Relational API —
duckdb.sql(), .filter(), .project(), .join() — lazy, chainable, returns DuckDBPyRelation
Key strengths:
- Reads CSV/Parquet/JSON directly from paths or buffers without loading into memory first
- Seamless pandas DataFrame and PyArrow Table interop via
from_df(), fetchdf(), to_arrow_table()
- Python scalar UDFs registered with
create_function() (native or arrow-backed)
- fsspec filesystem integration for S3, GCS, Azure, and in-memory storage
- ADBC driver included (
adbc_driver_duckdb)
Usage
Quick start — top-level convenience functions
import duckdb
# Query returns DuckDBPyRelation (lazy)
rel = duckdb.sql("SELECT 42 as x, 'hello' as y")
rel.show()
# Read files directly
rel = duckdb.read_parquet("data/*.parquet")
rel = duckdb.read_csv("data.csv", header=True)
rel = duckdb.read_json("data.json")
# Convert to pandas / PyArrow
df = rel.df() # pandas DataFrame
table = rel.to_arrow_table() # pyarrow.Table
reader = rel.to_arrow_reader() # streaming RecordBatchReader
Connection-based workflow
import duckdb
conn = duckdb.connect("my_db.duckdb") # persistent; ":memory:" is default
# Register a pandas DataFrame as a virtual table
conn.register("sales", sales_df)
# Execute SQL, get Relation back
rel = conn.sql("SELECT region, SUM(amount) FROM sales GROUP BY region")
rel.show()
# Standard DB-API 2.0 cursor interface
cursor = conn.cursor()
cursor.execute("SELECT * FROM sales WHERE amount > ?", [1000])
rows = cursor.fetchall()
conn.close()
Relational API chaining (lazy evaluation)
rel = (duckdb.from_df(df)
.filter("amount > 100")
.project("region, customer_id, amount * 1.1 as taxed_amount")
.order("taxed_amount DESC")
.limit(10))
rel.show()
Python UDFs
import duckdb
def double_it(x):
return x * 2
duckdb.create_function("double_it", double_it, ["integer"], "integer")
duckdb.sql("SELECT double_it(i) FROM range(5)").show()
Gotchas
- Default connection is
:memory: — data disappears when the process exits. Pass a file path to connect() for persistence.
fetch_arrow_table() and fetch_record_batch() are deprecated — use to_arrow_table() and to_arrow_reader() instead (same on both Connection and Relation).
- Relations are lazy —
.filter(), .project(), .join() etc. build a query plan. Results materialize only on .show(), .fetchall(), .df(), .execute(), or .create().
conn.register() creates a virtual table reference — it holds a Python object alive as long as the view/table exists in DuckDB catalog. Unregister with conn.unregister("name") to release.
- UDF parameter types must match exactly —
create_function("fn", fn_impl, ["bigint"], "varchar") requires input columns to be castable to BIGINT. Mismatched types raise InvalidInputException.
- Arrow UDFs receive ChunkedArrays — use
@duckdb.udf.vectorized decorator or annotate parameters with pa.ChunkedArray for arrow-mode UDFs.
conn.pl() returns Polars DataFrame — requires polars installed. Use lazy=True for LazyFrame.
- Free-threaded Python (3.13t, 3.14t) is not supported — the production client does not work with free-threaded builds.
conn.duplicate() clones a connection sharing the same database but with independent transaction state. Useful for concurrent queries on the same DB.
References
- 01-connection-api — connect, execute, cursor, transactions, config
- 02-relational-api — DuckDBPyRelation: lazy chaining, joins, aggregations, exports
- 03-data-io — CSV, Parquet, JSON read/write with options
- 04-udfs — Python scalar UDFs (native and arrow), type annotations, null handling
- 05-types-values — DuckDBPyType, sqltypes constants, Value classes, DB-API type objects
- 06-integrations — pandas, PyArrow, Polars, NumPy, fsspec, ADBC, Spark compat
1---2name: duckdb-python-1-5-43description: duckdb-python 1.5.44---56# duckdb-python 1.5.478DuckDB Python client providing in-process analytical SQL database with zero-config deployment. Runs entirely in-process (no server), supports pandas, PyArrow, Polars, and NumPy natively.910## Overview1112DuckDB is a columnar OLAP engine that runs inside the Python process. Two main API styles:1314- **Connection/DB-API 2.0** — `duckdb.connect()`, `conn.execute()`, `fetchall()` — standard cursor interface15- **Relational API** — `duckdb.sql()`, `.filter()`, `.project()`, `.join()` — lazy, chainable, returns `DuckDBPyRelation`1617Key strengths:18- Reads CSV/Parquet/JSON directly from paths or buffers without loading into memory first19- Seamless pandas DataFrame and PyArrow Table interop via `from_df()`, `fetchdf()`, `to_arrow_table()`20- Python scalar UDFs registered with `create_function()` (native or arrow-backed)21- fsspec filesystem integration for S3, GCS, Azure, and in-memory storage22- ADBC driver included (`adbc_driver_duckdb`)2324## Usage2526### Quick start — top-level convenience functions2728```python29import duckdb3031# Query returns DuckDBPyRelation (lazy)32rel = duckdb.sql("SELECT 42 as x, 'hello' as y")33rel.show()3435# Read files directly36rel = duckdb.read_parquet("data/*.parquet")37rel = duckdb.read_csv("data.csv", header=True)38rel = duckdb.read_json("data.json")3940# Convert to pandas / PyArrow41df = rel.df() # pandas DataFrame42table = rel.to_arrow_table() # pyarrow.Table43reader = rel.to_arrow_reader() # streaming RecordBatchReader44```4546### Connection-based workflow4748```python49import duckdb5051conn = duckdb.connect("my_db.duckdb") # persistent; ":memory:" is default5253# Register a pandas DataFrame as a virtual table54conn.register("sales", sales_df)5556# Execute SQL, get Relation back57rel = conn.sql("SELECT region, SUM(amount) FROM sales GROUP BY region")58rel.show()5960# Standard DB-API 2.0 cursor interface61cursor = conn.cursor()62cursor.execute("SELECT * FROM sales WHERE amount > ?", [1000])63rows = cursor.fetchall()6465conn.close()66```6768### Relational API chaining (lazy evaluation)6970```python71rel = (duckdb.from_df(df)72 .filter("amount > 100")73 .project("region, customer_id, amount * 1.1 as taxed_amount")74 .order("taxed_amount DESC")75 .limit(10))7677rel.show()78```7980### Python UDFs8182```python83import duckdb8485def double_it(x):86 return x * 28788duckdb.create_function("double_it", double_it, ["integer"], "integer")89duckdb.sql("SELECT double_it(i) FROM range(5)").show()90```9192## Gotchas9394- **Default connection is `:memory:`** — data disappears when the process exits. Pass a file path to `connect()` for persistence.95- **`fetch_arrow_table()` and `fetch_record_batch()` are deprecated** — use `to_arrow_table()` and `to_arrow_reader()` instead (same on both Connection and Relation).96- **Relations are lazy** — `.filter()`, `.project()`, `.join()` etc. build a query plan. Results materialize only on `.show()`, `.fetchall()`, `.df()`, `.execute()`, or `.create()`.97- **`conn.register()` creates a virtual table reference** — it holds a Python object alive as long as the view/table exists in DuckDB catalog. Unregister with `conn.unregister("name")` to release.98- **UDF parameter types must match exactly** — `create_function("fn", fn_impl, ["bigint"], "varchar")` requires input columns to be castable to `BIGINT`. Mismatched types raise `InvalidInputException`.99- **Arrow UDFs receive ChunkedArrays** — use `@duckdb.udf.vectorized` decorator or annotate parameters with `pa.ChunkedArray` for arrow-mode UDFs.100- **`conn.pl()` returns Polars DataFrame** — requires `polars` installed. Use `lazy=True` for `LazyFrame`.101- **Free-threaded Python (3.13t, 3.14t) is not supported** — the production client does not work with free-threaded builds.102- **`conn.duplicate()` clones a connection** sharing the same database but with independent transaction state. Useful for concurrent queries on the same DB.103104## References105106- [01-connection-api](references/01-connection-api.md) — connect, execute, cursor, transactions, config107- [02-relational-api](references/02-relational-api.md) — DuckDBPyRelation: lazy chaining, joins, aggregations, exports108- [03-data-io](references/03-data-io.md) — CSV, Parquet, JSON read/write with options109- [04-udfs](references/04-udfs.md) — Python scalar UDFs (native and arrow), type annotations, null handling110- [05-types-values](references/05-types-values.md) — DuckDBPyType, sqltypes constants, Value classes, DB-API type objects111- [06-integrations](references/06-integrations.md) — pandas, PyArrow, Polars, NumPy, fsspec, ADBC, Spark compat