Mysql
 sql >> Base de données >  >> RDS >> Mysql

Comment connecter à distance la base de données MySQL à l'aide de Python + SQLAlchemy ?

La réponse classique à ce problème est d'utiliser 127.0.0.1 ou l'IP de l'hôte ou le nom d'hôte au lieu du "nom spécial" localhost . À partir de la documentation :

Et plus tard :

Cependant, cette astuce simple ne semble pas fonctionner dans votre cas, vous devez donc en quelque sorte forcer l'utilisation d'un socket TCP. Comme vous l'avez expliqué vous-même, lors de l'appel de mysql en ligne de commande, vous utilisez le --protocol tcp option.

Comme expliqué ici , à partir de SQLAlchemy, vous pouvez transmettre les options pertinentes (le cas échéant) à votre pilote sous forme d'options d'URL ou en utilisant le connect_args argument de mot-clé.

Par exemple en utilisant PyMySQL , sur un système de test que j'ai configuré à cet effet (MariaDB 10.0.12, SQLAlchemy 0.9.8 et PyMySQL 0.6.2) j'ai obtenu les résultats suivants :

>>> 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',)]

Comme vous l'avez remarqué, les deux utiliseront une connexion TCP (je le sais à cause du numéro de port après le nom d'hôte). D'autre part :

>>> 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',)]

Aucun port après le nom d'hôte :il s'agit d'un socket UNIX.