Servidor Quack y conexi贸n remota en dos cuadernos Jupyter independientes¶
Demostraci贸n en dos cuadernos Jupyter independientes: uno dedicado exclusivamente al servidor y otro al cliente. Ambos se ejecutan en la misma m谩quina (todo local) y se comunican a trav茅s de localhost.
馃摀 Cuaderno 1: servidor_quack.ipynb¶
Inicia un servidor Quack en segundo plano. Debe permanecer ejecut谩ndose mientras se usa el cuaderno cliente.
Celda 1: Importaciones y configuraci贸n¶
import duckdb
import threading
import time
# --- Par谩metros del servidor (aj煤star si es necesario) ---
HOST = "localhost"
PORT = 9494
TOKEN = "demo_token_local_2026" # M铆nimo 4 caracteres, seg煤n la documentaci贸n
print(f"DuckDB versi贸n: {duckdb.__version__}")
Celda 2: Funci贸n que inicializa el servidor¶
def iniciar_servidor_quack():
"""
Crea una conexi贸n dedicada, instala/carga la extensi贸n quack
y deja el servidor escuchando en localhost:PORT.
"""
con = duckdb.connect()
con.install_extension("quack")
con.load_extension("quack")
con.execute(f"""
CALL quack_serve(
'quack:{HOST}:{PORT}',
token = '{TOKEN}',
allow_other_hostname => false -- solo localhost, como pediste
);
""")
print(f"Servidor Quack escuchando en quack:{HOST}:{PORT}")
# Mantenemos la conexi贸n viva (y con ella el servidor)
while True:
time.sleep(1)
Celda 3: Lanzar el servidor en un hilo background (daemon=True)¶
hilo_servidor = threading.Thread(target=iniciar_servidor_quack, daemon=True)
hilo_servidor.start()
# Damos un margen para que el servidor se inicialice
time.sleep(1)
print("Hilo del servidor iniciado. Pasar al cuaderno cliente.")
Celda 4 (opcional): Verificaci贸n r谩pida del servidor¶
Comprobar desde el propio cuaderno del servidor que quack_serve ha devuelto la informaci贸n esperada ejecutando esta consulta antes de lanzar el hilo (o en una conexi贸n aparte). Lo m谩s sencillo es confiar en el mensaje de la Celda 3 y pasar directamente al cliente.
Nota importante
El hilo es un proceso daemon por lo que el servidor se detendr谩 autom谩ticamente si se reinicia el kernel python. Por tanto, si se cierra el cuaderno sin reiniciar, el hilo podr铆a seguir vivo hasta que el proceso de Python termine.
馃摀 Cuaderno 2: cliente_quack.ipynb¶
Este cuaderno contiene dos apartados independientes:
- Conexi贸n v铆a Quack
- Conexi贸n a MariaDB/MySQL local
Ambas usan CONNECT, la nueva sentencia de DuckDB 2.0 que redirige la sesi贸n al motor remoto y aplica pushdown de consultas.
Celda 1: Importaciones y verificaci贸n¶
import duckdb
import pandas as pd
print(f"DuckDB versi贸n: {duckdb.__version__}")
馃敼 Caso A: Conexi贸n al servidor Quack local¶
Celda 2: Adjuntar y conectar al servidor Quack¶
con = duckdb.connect()
# 1) Instalar y cargar la extensi贸n quack en el cliente (si no est谩 ya)
con.install_extension("quack")
con.load_extension("quack")
# 2) Adjuntar el servidor remoto con el token acordado
con.execute(f"""
ATTACH 'quack:localhost:9494' AS qk (TOKEN 'demo_token_local_2026');
""")
# 3) Redirigir la sesi贸n al servidor Quack
con.execute("CONNECT qk;")
print("Sesi贸n redirigida al servidor Quack")
Celda 3: Crear datos y consultar de forma remota¶
# Estas sentencias se ejecutan en el servidor
con.execute("""
CREATE OR REPLACE TABLE ventas_quack (
producto VARCHAR,
unidades INTEGER,
precio DOUBLE
);
INSERT INTO ventas_quack VALUES
('teclado', 10, 25.5),
('rat贸n', 15, 12.0),
('monitor', 5, 180.0);
""")
df_quack = con.execute("""
SELECT producto, unidades * precio AS ingreso
FROM ventas_quack
ORDER BY ingreso DESC;
""").df()
print("Resultados obtenidos desde el servidor Quack:")
display(df_quack)
Celda 4: Desconectar y cerrar¶
con.execute("DISCONNECT;")
con.close()
print("Cliente Quack desconectado.")
馃敼 Caso B: Conexi贸n a servidor MariaDB/MySQL (local)¶
Celda 5: Instalar extensi贸n y conectar a MySQL/MariaDB¶
con_mysql = duckdb.connect()
# Instalar y cargar la extensi贸n mysql (soporta MySQL y MariaDB)
con_mysql.install_extension("mysql")
con_mysql.load_extension("mysql")
# Usar CONNECT directamente con una cadena de conexi贸n.
# La cadena debe empezar por "mysql:" y usar formato key=value (estilo PostgreSQL),
# NO aplica el formato DSN "mysql://usuario:clave@host/db".
con_mysql.execute("""
CONNECT 'mysql:host=localhost user=eurostar password=eurostar database=eurostar';
""")
print("Sesi贸n redirigida al servidor MySQL/MariaDB")
Consulta SQL¶
con_mysql.execute("""
select StopCode, StopName, StopLat, StopLng from eurostar.Stations where Country like 'F';
""")
Mostrar resultados¶
output = con_mysql.fetchall()
for i in output:
print(i)
Alternativa con ATTACH + CONNECT
Es posible separar los pasos:
con_mysql.execute("""
ATTACH 'host=localhost user=eurostar password=eurostar database=eurostar'
AS mysql_local (TYPE mysql_scanner);
""")
con_mysql.execute("CONNECT mysql_local;")
Celda 6: Resultado en un dataframe Pandas¶
# Esta consulta se ejecuta directamente en el servidor MySQL/MariaDB
# gracias al optimizador de pushdown remoto de DuckDB 2.0
df_mysql = con_mysql.execute("""
SELECT table_name, table_rows
FROM information_schema.tables
WHERE table_schema = 'eurostar'
ORDER BY table_name;
""").df()
print("Tablas en la base de datos MySQL/MariaDB local:")
display(df_mysql)
Celda 7: Desconectar¶
con_mysql.execute("DISCONNECT;")
con_mysql.close()
print("Cliente MySQL/MariaDB desconectado.")
馃Л Resumen de cada cuaderno¶
| Cuaderno | Funcionalidad | Sentencias clave |
|---|---|---|
| Servidor | Arrancar un endpoint Quack local | CALL quack_serve(...) |
| Cliente | A) Conectarse a un DuckDB remoto | ATTACH ... (TOKEN ...); CONNECT qk; |
| Cliente | B) Conectarse a MariaDB/MySQL | CONNECT 'mysql:host=... user=... database=...' o ATTACH ... (TYPE mysql_scanner); CONNECT ... |
Ambas demos usan exclusivamente localhost y no exponen ning煤n servicio a la red externa. Para ajustar el puerto, el token o las credenciales de MySQL, basta con modificar las variables al inicio de cada cuaderno. |