Saltar al contenido

¿Cómo conectar la base de datos MySQL usando Python+SQLAlchemy de forma remota?

Indagamos en el mundo online para darte la respuesta para tu inquietud, si continúas con dudas déjanos tu duda y te respondemos con gusto.

Solución:

La respuesta clásica a este problema es usar 127.0.0.1 o el IP del anfitrión o el nombre de host en lugar del “nombre especial” localhost. De la documentación:

[…] conexiones en Unix para servidor local se hacen usando un archivo de socket Unix por defecto

Y después:

En Unix, los programas MySQL tratan el nombre de host servidor local especialmente, de una manera que probablemente sea diferente de lo que espera en comparación con otros programas basados ​​en la red. Para las conexiones a localhost, los programas MySQL intentan conectarse al servidor local mediante un archivo de socket Unix. Esto ocurre incluso si se proporciona la opción –port o -P para especificar un número de puerto. Para asegurarse de que el cliente establezca una conexión TCP/IP con el servidor local, use –host o -h para especificar un valor de nombre de host de 127.0.0.1, o la dirección IP o el nombre del servidor local.


Sin embargo, este simple truco no parece funcionar en tu caso, así que tienes que fuerza el uso de un socket TCP. Como tú mismo lo explicaste, al invocar mysql en la línea de comando, usas el --protocol tcp opción.

Como se explica aquí, desde SQLAlchemy, puede pasar las opciones relevantes (si las hay) a su controlador como opciones de URL o utilizando el connect_args argumento de palabra clave.

Por ejemplo usando PyMySQLen un sistema de prueba que configuré para ese propósito (MariaDB 10.0.12, SQLAlchemy 0.9.8 y PyMySQL 0.6.2) obtuve los siguientes resultados:

>>> engine = create_engine(
      "mysql+pymysql://sylvain:[email protected]/db?host=localhost?port=3306")
#                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
#                               Force TCP socket. Notice the two uses of `?`
#                               Normally URL options should use `?` and `&`  
#                               after that. But that doesn't work here (bug?)
>>> conn = engine.connect()
>>> conn.execute("SELECT host FROM INFORMATION_SCHEMA.PROCESSLIST WHERE ID = CONNECTION_ID()").fetchall()
[('localhost:54164',)]

# Same result by using 127.0.0.1 instead of localhost: 
>>> engine = create_engine(
      "mysql+pymysql://sylvain:[email protected]/db?host=localhost?port=3306")
>>> conn = engine.connect()
>>> conn.execute("SELECT host FROM INFORMATION_SCHEMA.PROCESSLIST WHERE ID = CONNECTION_ID()").fetchall()
[('localhost:54164',)]

# Alternatively, using connect_args:
>>> engine = create_engine("mysql+pymysql://sylvain:[email protected]/db",
                       connect_args= dict(host='localhost', port=3306))
>>> conn = engine.connect()
>>> conn.execute("SELECT host FROM INFORMATION_SCHEMA.PROCESSLIST WHERE ID = CONNECTION_ID()").fetchall()
[('localhost:54353',)]

Como notó, ambos usarán una conexión TCP (lo sé por el número de puerto después del nombre de host). Por otro lado:

>>> engine = create_engine(
      "mysql+pymysql://sylvain:[email protected]/db?unix_socket=/path/to/mysql.sock")
#                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#                               Specify the path to mysql.sock in
#                               the `unix_socket` option will force
#                               usage of a UNIX socket

>>> conn = engine.connect()
>>> conn.execute("SELECT host FROM INFORMATION_SCHEMA.PROCESSLIST WHERE ID = CONNECTION_ID()").fetchall()
[('localhost',)]

# Same result by using 127.0.0.1 instead of localhost: 
>>> engine = create_engine(
      "mysql+pymysql://sylvain:[email protected]/db?unix_socket=/path/to/mysql.sock")
>>> conn = engine.connect()
>>> conn.execute("SELECT host FROM INFORMATION_SCHEMA.PROCESSLIST WHERE ID = CONNECTION_ID()").fetchall()
[('localhost',)]

# Alternatively, using connect_args:
>>> engine = create_engine("mysql+pymysql://sylvain:[email protected]/db",
                       connect_args= dict(unix_socket="/path/to/mysql.sock"))
>>> conn = engine.connect()
>>> conn.execute("SELECT host FROM INFORMATION_SCHEMA.PROCESSLIST WHERE ID = CONNECTION_ID()").fetchall()
[('localhost',)]

Sin puerto después de la nombre de host: este es un zócalo UNIX.

En mi configuración (estoy usando mysql-python) solo uso 127.0.0.1 en lugar de localhost en MySQL SQLAlchemy url funciona. La URL completa que estoy usando exactamente para ese escenario (túnel con puerto local 3307) es:

mysql:/user:[email protected]:3307/

Estoy usando SQLAlchemy 1.0.5, pero supongo que eso no importa demasiado…

Esto funcionó para mí:

import pandas as pd
import pymysql
from sqlalchemy import create_engine

cnx = create_engine('mysql+pymysql://:@/')    
df = pd.read_sql('SELECT * FROM ', cnx) #read the entire table

Donde las credenciales se agregan a la base de datos mysql de esta manera:

CREATE USER '' IDENTIFIED BY '';
GRANT ALL PRIVILEGES ON *.* TO '' WITH GRANT OPTION;
FLUSH PRIVILEGES;

valoraciones y reseñas

Si sostienes algún enigma y forma de renovar nuestro sección te invitamos escribir una reseña y con placer lo leeremos.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *