Skip to content

Python API 简介

Python API是 DuckDB 的 Python 绑定。他实现了 Python DB-API 2.0

安装

Bash
pip install duckdb

conda install -c conda-forge python-duckdb

DuckDB 需要 Python3.7 及以上版本

架构

DuckDB 的 Python API 提供了两套不同的架构:

  • DB API: 实现了 Python 的 DB-API2.0 接口
  • Relational API: 关系 API,它使用增量来构造查询,整个执行过程都是惰性的直到调用触发执行的方法,并且提供了 ORM 式的构造 SELECT 语句的方式

同时还提供了一些外围的核心组件:

  • Types API: 用于隐式转换数据库数据类型和 Python 数据类型,并且提供了接口来构造复杂数据类型
  • Function API: 为 DuckDB 绑定用户自定义过程函数(UDF)
  • Expression API: 动态构造查询表达式

DBAPI 和 Relational API

他们是两种不同的工作模式,对于DB API实现了 Python DB-API 2.0 接口,标准的操作方式: duckdb.connect() → Connection.cursor() → Cursor.execute() -> Curosr.fetchall()

Relational API比较特殊,首先他只能执行数据查询语言即 SELECT 语句,并且他自身就是一个只读视图能够在查询语言中使用

通常情况下任何一个查询操作都能够由两种操作方式实现:

Python
import duckdb

## DuckDBPyRelation 操作方式
# 惰性非阻塞,直接创建一个虚拟视图
rel = duckdb.sql("SELECT * from read_csv('股吧数据-帖子详情(2010-2019)-版本3.csv',ignore_errors=True,max_line_size=20000000)")
# 同样是惰性的,这就是不断调用来逼近需要的结果视图
# 同时 rel 是 DuckDBPyRelation 对象因此能够位于 sql 语句中
year_2011 = duckdb.sql("SELECT * FROM rel WHERE extract(year from 帖子发布时间)=2011")
# 执行读取操作来真正执行 SQL 语句
year_2011.fetch_df()

## DuckDBPyConnection 操作方式
# 直接在内存数据库中构建表,表中数据由 csv 文件构成
conn = duckdb.execute("CREATE TABLE new_table AS SELECT * from read_csv('股吧数据-帖子详情(2010-2019)-版本3.csv',ignore_errors=True,max_line_size=20000000)")
# 上面的等价操作
conn = duckdb.execute("SELECT * from read_csv('股吧数据-帖子详情(2010-2019)-版本3.csv',ignore_errors=True,max_line_size=20000000)")
# conn.table() 返回的就是 DuckDBPyRelation 对象,相当于在内存数据库中创建了表
new_table = conn.table()
# 执行查询
# 再次强调 FROM 后面必须是表,可以是 CREATE TABLE 创建的也可以是方法返回的 DuckDBPyRelation 对象
year_2011 = conn.execute("SELECT * FROM new_table WHERE extract(year from 帖子发布时间)=2011")
# 读取数据
year_2011.fetchall()

上面两种方式都实现了同一个结果,当时也有一些区别:

  • DB API操作模式下,创建的表是真正存在于内存中或者 DuckDB 数据库文件中,他不会被释放,因此再次执行类似 conn.execute("SELECT * FROM new_table WHERE extract(year from 帖子发布时间)=2012") 这样的操作速度会非常块,因为不需要在读取 csv 来构建表了,但是这也意味着如果数据非常大会导致内存溢出
  • Relational API操作模式下,并不会保存创建的表,虚拟视图在调用 year_2021.fetch_df() 后被释放了,也就是说没有办法复用表,再次执行类似命令还需要重新读取 csv

Python 生态交互

DuckDB 一个非常杀手锏的功能就是她与 Python 的整个生态进行了融合: