Python-API
Installation Um den DuckDB-Python-Client zu verwenden, besuchen Sie die Python-Installationsseite.
Die aktuelle stabile Version des DuckDB-Python-Clients ist 1.5.5.
Installation
Die DuckDB-Python-API kann mit pip installiert werden: pip install duckdb. Details finden Sie auf der Installationsseite. DuckDB kann auch mit conda installiert werden: conda install python-duckdb -c conda-forge.
Python-Version: DuckDB benötigt Python 3.9 oder neuer.
Grundlegende API-Nutzung
Die einfachste Art, SQL-Abfragen mit DuckDB auszuführen, ist der Befehl duckdb.sql.
import duckdb
duckdb.sql("SELECT 42").show()Damit werden Abfragen über eine In-Memory-Datenbank ausgeführt, die global im Python-Modul gespeichert ist. Das Ergebnis der Abfrage wird als Relation zurückgegeben. Eine Relation ist eine symbolische Darstellung der Abfrage. Die Abfrage wird erst ausgeführt, wenn das Ergebnis abgerufen oder zur Ausgabe auf dem Bildschirm angefordert wird.
Relationen können in nachfolgenden Abfragen referenziert werden, indem sie in Variablen gespeichert und als Tabellen verwendet werden. So können Abfragen schrittweise aufgebaut werden.
import duckdb
r1 = duckdb.sql("SELECT 42 AS i")duckdb.sql("SELECT i * 2 AS k FROM r1").show()Dateneingabe
DuckDB kann Daten aus einer Vielzahl von Formaten einlesen – sowohl von der Festplatte als auch aus dem Speicher. Weitere Informationen finden Sie auf der Seite Dateneingabe.
import duckdb
duckdb.read_csv("example.csv") # read a CSV file into a Relationduckdb.read_parquet("example.parquet") # read a Parquet file into a Relationduckdb.read_json("example.json") # read a JSON file into a Relation
duckdb.sql("SELECT * FROM 'example.csv'") # directly query a CSV fileduckdb.sql("SELECT * FROM 'example.parquet'") # directly query a Parquet fileduckdb.sql("SELECT * FROM 'example.json'") # directly query a JSON fileDataFrames
DuckDB kann Pandas-DataFrames, Polars-DataFrames und Arrow-Tabellen direkt abfragen.
Beachten Sie, dass diese schreibgeschützt sind, d. h. das Bearbeiten dieser Tabellen über INSERT- oder UPDATE-Anweisungen ist nicht möglich.
Pandas
Um ein Pandas-DataFrame direkt abzufragen, führen Sie aus:
import duckdbimport pandas as pd
pandas_df = pd.DataFrame({"a": [42]})duckdb.sql("SELECT * FROM pandas_df")┌───────┐│ a ││ int64 │├───────┤│ 42 │└───────┘Polars
Um ein Polars-DataFrame direkt abzufragen, führen Sie aus:
import duckdbimport polars as pl
polars_df = pl.DataFrame({"a": [42]})duckdb.sql("SELECT * FROM polars_df")┌───────┐│ a ││ int64 │├───────┤│ 42 │└───────┘PyArrow
Um eine PyArrow-Tabelle direkt abzufragen, führen Sie aus:
import duckdbimport pyarrow as pa
arrow_table = pa.Table.from_pydict({"a": [42]})duckdb.sql("SELECT * FROM arrow_table")┌───────┐│ a ││ int64 │├───────┤│ 42 │└───────┘Ergebnisumwandlung
DuckDB unterstützt die effiziente Umwandlung von Abfrageergebnissen in eine Vielzahl von Formaten. Weitere Informationen finden Sie auf der Seite Ergebnisumwandlung.
import duckdb
duckdb.sql("SELECT 42").fetchall() # Python objectsduckdb.sql("SELECT 42").df() # Pandas DataFrameduckdb.sql("SELECT 42").pl() # Polars DataFrameduckdb.sql("SELECT 42").arrow() # Arrow Tableduckdb.sql("SELECT 42").fetchnumpy() # NumPy ArraysDaten auf die Festplatte schreiben
DuckDB unterstützt das direkte Schreiben von Relation-Objekten in einer Vielzahl von Formaten auf die Festplatte. Alternativ kann die Anweisung COPY verwendet werden, um Daten per SQL auf die Festplatte zu schreiben.
import duckdb
duckdb.sql("SELECT 42").write_parquet("out.parquet") # Write to a Parquet fileduckdb.sql("SELECT 42").write_csv("out.csv") # Write to a CSV fileduckdb.sql("COPY (SELECT 42) TO 'out.parquet'") # Copy to a Parquet fileVerbindungsoptionen
Anwendungen können über die Methode duckdb.connect() eine neue DuckDB-Verbindung öffnen.
Eine In-Memory-Datenbank verwenden
Wenn DuckDB über duckdb.sql() verwendet wird, arbeitet es mit einer In-Memory-Datenbank, d. h. es werden keine Tabellen auf der Festplatte gespeichert.
Ein Aufruf der Methode duckdb.connect() ohne Argumente gibt eine Verbindung zurück, die ebenfalls eine In-Memory-Datenbank verwendet:
import duckdb
con = duckdb.connect()con.sql("SELECT 42 AS x").show()Persistenter Speicher
duckdb.connect(dbname) erzeugt eine Verbindung zu einer persistenten Datenbank.
Alle in diese Verbindung geschriebenen Daten werden gespeichert und können durch erneutes Verbinden mit derselben Datei wieder geladen werden – sowohl aus Python als auch aus anderen DuckDB-Clients.
import duckdb
# create a connection to a file called 'file.db'con = duckdb.connect("file.db")# create a table and load data into itcon.sql("CREATE TABLE test (i INTEGER)")con.sql("INSERT INTO test VALUES (42)")# query the tablecon.table("test").show()# explicitly close the connectioncon.close()# Note: connections also closed implicitly when they go out of scopeSie können auch einen Kontextmanager verwenden, um sicherzustellen, dass die Verbindung geschlossen wird:
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 automaticallyKonfiguration
duckdb.connect() akzeptiert ein Dictionary config, in dem Konfigurationsoptionen angegeben werden können. Zum Beispiel:
import duckdb
con = duckdb.connect(config = {'threads': 1})Um die Speicherversion anzugeben, übergeben Sie die Option storage_compatibility_version:
import duckdb
con = duckdb.connect(config = {'storage_compatibility_version': 'latest'})Verbindungsobjekt und Modul
Das Verbindungsobjekt und das Modul duckdb können austauschbar verwendet werden – sie unterstützen dieselben Methoden. Der einzige Unterschied besteht darin, dass beim Modul duckdb eine globale In-Memory-Datenbank verwendet wird.
Wenn Sie ein Paket entwickeln, das andere nutzen sollen, und DuckDB im Paket verwenden, wird empfohlen, Verbindungsobjekte zu erzeugen, statt die Methoden des Moduls
duckdbzu nutzen. Das liegt daran, dass das Modulduckdbeine gemeinsame globale Datenbank verwendet – was zu schwer nachvollziehbaren Problemen führen kann, wenn es aus mehreren verschiedenen Paketen heraus verwendet wird.
Verbindungen in parallelen Python-Programmen verwenden
Threadsicherheit von duckdb.sql() und der globalen Verbindung
duckdb.sql() und duckdb.connect(':default:') verwenden eine gemeinsame globale In-Memory-Verbindung. Diese Verbindung ist nicht threadsicher, und das Ausführen von Abfragen darauf aus mehreren Threads kann zu Problemen führen. Um DuckDB parallel auszuführen, muss jeder Thread seine eigene Verbindung haben:
def good_use(): con = duckdb.connect() # uses new connection con.sql("SELECT 1").fetchall()Umgekehrt könnten die folgenden Varianten zu Nebenläufigkeitsproblemen führen, weil sie sich auf eine globale Verbindung stützen:
def bad_use(): con = duckdb.connect(':default:') # uses global connection return con.sql("SELECT 1").fetchall()Oder:
def also_bad(): return duckdb.sql("SELECT 1").fetchall() # uses global connectionVermeiden Sie duckdb.sql() oder das Teilen einer einzelnen Verbindung über Threads hinweg.
Über cursor()
Eine Methode DuckDBPyConnection.cursor() erzeugt ein weiteres Handle auf dieselbe Verbindung. Sie öffnet keine neue Verbindung. Daher können alle von einer Verbindung erzeugten Cursor nicht gleichzeitig Abfragen ausführen.
Community-Erweiterungen
Um Community-Erweiterungen zu laden, verwenden Sie das Argument repository="community" mit der Methode install_extension.
Installieren und laden Sie beispielsweise die Community-Erweiterung h3 wie folgt:
import duckdb
con = duckdb.connect()con.install_extension("h3", repository="community")con.load_extension("h3")Unsignierte Erweiterungen
Um unsignierte Erweiterungen zu laden, verwenden Sie:
con = duckdb.connect(config={"allow_unsigned_extensions": "true"})Warning Laden Sie unsignierte Erweiterungen nur aus Quellen, denen Sie vertrauen. Vermeiden Sie das Laden unsignierter Erweiterungen über HTTP. Konsultieren Sie die Seite DuckDB absichern für Richtlinien, wie Sie DuckDB sicher einrichten.