⌘+k ctrl+k
1.4 (LTS)
搜索快捷键 cmd + k | ctrl + k
Python API

DuckDB Python 客户端的最新稳定版本是 1.5.0。

安装

可以使用 pip 安装 DuckDB Python API:pip install duckdb。详情请参阅安装页面。也可以使用 conda 安装 DuckDB:conda install python-duckdb -c conda-forge

Python 版本: DuckDB 需要 Python 3.9 或更高版本。

基本 API 用法

使用 DuckDB 运行 SQL 查询最直接的方法是使用 duckdb.sql 命令。

import duckdb

duckdb.sql("SELECT 42").show()

这将使用存储在 Python 模块内部全局的内存数据库来执行查询。查询结果作为关系(Relation)返回。关系是查询的符号表示。除非获取结果或请求将其打印到屏幕上,否则查询不会执行。

关系可以通过将它们存储在变量中并将其用作表,从而在后续查询中引用。通过这种方式,可以逐步构建查询。

import duckdb

r1 = duckdb.sql("SELECT 42 AS i")
duckdb.sql("SELECT i * 2 AS k FROM r1").show()

数据输入

DuckDB 可以摄取多种格式的数据——包括磁盘数据和内存数据。更多信息请参阅数据摄取页面

import duckdb

duckdb.read_csv("example.csv")                # read a CSV file into a Relation
duckdb.read_parquet("example.parquet")        # read a Parquet file into a Relation
duckdb.read_json("example.json")              # read a JSON file into a Relation

duckdb.sql("SELECT * FROM 'example.csv'")     # directly query a CSV file
duckdb.sql("SELECT * FROM 'example.parquet'") # directly query a Parquet file
duckdb.sql("SELECT * FROM 'example.json'")    # directly query a JSON file

数据帧 (DataFrames)

DuckDB 可以直接查询 Pandas DataFrames、Polars DataFrames 和 Arrow 表。请注意,这些是只读的,即无法通过 INSERTUPDATE 语句编辑这些表。

Pandas

要直接查询 Pandas DataFrame,请运行

import duckdb
import pandas as pd

pandas_df = pd.DataFrame({"a": [42]})
duckdb.sql("SELECT * FROM pandas_df")
┌───────┐
│   a   │
│ int64 │
├───────┤
│    42 │
└───────┘

Polars

要直接查询 Polars DataFrame,请运行

import duckdb
import polars as pl

polars_df = pl.DataFrame({"a": [42]})
duckdb.sql("SELECT * FROM polars_df")
┌───────┐
│   a   │
│ int64 │
├───────┤
│    42 │
└───────┘

PyArrow

要直接查询 PyArrow 表,请运行

import duckdb
import pyarrow as pa

arrow_table = pa.Table.from_pydict({"a": [42]})
duckdb.sql("SELECT * FROM arrow_table")
┌───────┐
│   a   │
│ int64 │
├───────┤
│    42 │
└───────┘

结果转换

DuckDB 支持将查询结果高效地转换为各种格式。更多信息请参阅结果转换页面

import duckdb

duckdb.sql("SELECT 42").fetchall()   # Python objects
duckdb.sql("SELECT 42").df()         # Pandas DataFrame
duckdb.sql("SELECT 42").pl()         # Polars DataFrame
duckdb.sql("SELECT 42").arrow()      # Arrow Table
duckdb.sql("SELECT 42").fetchnumpy() # NumPy Arrays

将数据写入磁盘

DuckDB 支持将关系对象直接以多种格式写入磁盘。或者,也可以使用 SQL 的 COPY 语句将数据写入磁盘。

import duckdb

duckdb.sql("SELECT 42").write_parquet("out.parquet") # Write to a Parquet file
duckdb.sql("SELECT 42").write_csv("out.csv")         # Write to a CSV file
duckdb.sql("COPY (SELECT 42) TO 'out.parquet'")      # Copy to a Parquet file

连接选项

应用程序可以通过 duckdb.connect() 方法打开一个新的 DuckDB 连接。

使用内存数据库

当通过 duckdb.sql() 使用 DuckDB 时,它在内存数据库上运行,即没有表会持久化到磁盘上。调用不带参数的 duckdb.connect() 方法会返回一个连接,该连接也使用内存数据库。

import duckdb

con = duckdb.connect()
con.sql("SELECT 42 AS x").show()

持久化存储

使用 duckdb.connect(dbname) 可以创建一个连接到持久化数据库的连接。写入该连接的任何数据都将被持久化,并且可以通过从 Python 或其他 DuckDB 客户端重新连接到同一个文件来重新加载。

import duckdb

# create a connection to a file called 'file.db'
con = duckdb.connect("file.db")
# create a table and load data into it
con.sql("CREATE TABLE test (i INTEGER)")
con.sql("INSERT INTO test VALUES (42)")
# query the table
con.table("test").show()
# explicitly close the connection
con.close()
# Note: connections also closed implicitly when they go out of scope

您还可以使用上下文管理器来确保连接被关闭

import duckdb

with duckdb.connect("file.db") as con:
    con.sql("CREATE TABLE test (i INTEGER)")
    con.sql("INSERT INTO test VALUES (42)")
    con.table("test").show()
    # the context manager closes the connection automatically

配置

duckdb.connect() 接受一个 config 字典,可以在其中指定配置选项。例如

import duckdb

con = duckdb.connect(config = {'threads': 1})

要指定存储版本,请传入 storage_compatibility_version 选项

import duckdb

con = duckdb.connect(config = {'storage_compatibility_version': 'latest'})

连接对象和模块

连接对象和 duckdb 模块可以互换使用——它们支持相同的方法。唯一的区别在于使用 duckdb 模块时,使用的是全局内存数据库。

如果您正在开发一个供他人使用的软件包,并在其中使用了 DuckDB,建议您创建连接对象,而不是使用 duckdb 模块上的方法。这是因为 duckdb 模块使用共享的全局数据库——如果从多个不同的软件包内部使用,这可能会导致难以调试的问题。

在并行 Python 程序中使用连接

duckdb.sql() 和全局连接的线程安全性

duckdb.sql()duckdb.connect(':default:') 使用共享的全局内存连接。此连接不是线程安全的,从多个线程对其运行查询可能会导致问题。要在并行环境中运行 DuckDB,每个线程必须拥有自己的连接。

def good_use():
    con = duckdb.connect()
    # uses new connection
    con.sql("SELECT 1").fetchall()

相反,以下操作可能会导致并发问题,因为它们依赖于全局连接

def bad_use():
    con = duckdb.connect(':default:')
    # uses global connection
    return con.sql("SELECT 1").fetchall()

def also_bad():
    return duckdb.sql("SELECT 1").fetchall()
    # uses global connection 

避免使用 duckdb.sql() 或跨线程共享单个连接。

关于 cursor()

DuckDBPyConnection.cursor() 方法可在同一个连接上创建另一个句柄。它不会打开新连接。因此,从同一个连接创建的所有游标都不能同时运行查询。

社区扩展

要加载社区扩展,请在 install_extension 方法中使用 repository="community" 参数。

例如,安装并加载 h3 社区扩展的操作如下

import duckdb

con = duckdb.connect()
con.install_extension("h3", repository="community")
con.load_extension("h3")

未签名扩展

要加载未签名扩展,请使用

con = duckdb.connect(config={"allow_unsigned_extensions": "true"})

警告:仅从您信任的来源加载未签名扩展。避免通过 HTTP 加载未签名扩展。有关如何以安全方式设置 DuckDB 的指南,请查阅保护 DuckDB 页面

本节页面

© 2025 DuckDB 基金会,阿姆斯特丹,荷兰
行为准则 商标使用指南