La primera vez que intenté Python
conectarme a clickhouse
la base de datos, pisé muchos hoyos. ¡Por la presente lo registro para ayudar a las generaciones futuras a cometer menos errores!
Entorno operativo:
- pitón 3.8.3
- clickhouse_driver==0.2.3
- clickhouse_sqlalchemy==0.2.0
- sqlalchemy==1.4.32
Dos formas de conectar clickhouse_driver
1.Cliente
Aprende de Internet
from clickhouse_driver import Client
client = Client(host=host, port=8123, database=database,user=user ,password=pw)
sql = 'SHOW TABLES'
res = client.execute(sql)
Error: UnexpectedPacketFromServerError: Código: 102
Motivo: problema de puerto, protocolo HTTP (puerto predeterminado 8123); protocolo TCP (nativo) (el número de puerto predeterminado es 9000), puerto tcp 9000 utilizado por clickhouse_driver en Python, DBeaver usa el protocolo HTTP para que el puerto 8123 pueda ser usado.
después de la modificación
from clickhouse_driver import Client
client = Client(host=host, port=9000, database=database,user=user ,password=pw)
sql = 'SHOW TABLES'
res = client.execute(sql)
Error: SocketTimeoutError: Código: 209.
Razón: pegue la solución mencionada por el autor en GitHub aquí, la razón por la que el portal
encuentra este error también es porque el puerto 9000 no está configurado. Sentirse muy confundido. Así que renuncié al Cliente y probé con otro método de conexión.
2.conectar
from clickhouse_driver import connect
#账号:密码@主机名:端口号/数据库
conn = connect(f'clickhouse://{user}:{pw}@{host}:9000/{database}')
cursor = conn.cursor()
cursor.execute('SHOW TABLES')
Reportado el mismo error, servido.
Finalmente abandoné clickhouse_driver e intenté resolverlo con éxito con clickhouse_sqlalchemy y sqlalchemy
clickhouse_sqlalchemy
Adjunte directamente el código para la conexión exitosa.
from clickhouse_sqlalchemy import make_session
from sqlalchemy import create_engine
import pandas as pd
conf = {
"user": "xxx",
"password": "xxx",
"server_host": "xx.xxx.xx.xxx",
"port": "8123",
"db": "xxx"
}
connection = 'clickhouse://{user}:{password}@{server_host}:{port}/{db}'.format(**conf)
engine = create_engine(connection, pool_size=100, pool_recycle=3600, pool_timeout=20)
sql = 'SHOW TABLES'
session = make_session(engine)
cursor = session.execute(sql)
try:
fields = cursor._metadata.keys
df = pd.DataFrame([dict(zip(fields, item)) for item in cursor.fetchall()])
finally:
cursor.close()
session.close()