如何使用Python + SQLAlchemy远程连接MySQL数据库?

问题描述 投票:10回答:3

我在远程访问MySQL时遇到困难。我使用SSH隧道,并希望使用Python + SQLALchemy连接数据库MySQL。

当我在控制台中使用MySQL客户端并指定“ ptotocol=TCP”时,一切都很好!我使用命令:

mysql -h localhost —protocol=TCP -u USER -p

我可以通过SSH隧道访问远程数据库。

但是,当我想使用Python + SQLAchemy连接到数据库时,找不到类似—protocol=TCP的选项否则,我只能连接到本地MySQL数据库。请告诉我,有没有一种方法可以使用SQLAlchemy。

python mysql tcp sqlalchemy ssh-tunnel
3个回答
19
投票

此问题的经典答案是使用127.0.0.1主机的IP主机名而不是“特殊名称” localhost。从documentation

[...]在Unix上与localhost的连接

以及以后:

在Unix上,MySQL程序特别对待主机名localhost],其方式可能与您期望的方式相比于其他基于网络的程序不同。对于与本地主机的连接,MySQL程序尝试使用Unix套接字文件连接到本地服务器。即使给--port或-P选项指定端口号,也会发生这种情况。为确保客户端与本地服务器建立TCP / IP连接,请使用--host或-h指定主机名值127.0.0.1或本地服务器的IP地址或名称。


但是,这种简单的技巧似乎不适用于您的情况,因此您必须以某种方式force

使用TCP套接字。正如您自己解释的那样,在命令行上调用mysql时,可以使用--protocol tcp选项。

如从SQLAlchemy所解释的here所述,您可以使用connect_args关键字参数将相关选项(如果有)作为URL选项传递给驱动程序。[]例如,使用

PyMySQL

,在为此目的而设置的测试系统(MariaDB 10.0.12,SQLAlchemy 0.9.8和PyMySQL 0.6.2)上,我得到了以下结果:>>> engine = create_engine( "mysql+pymysql://sylvain:passwd@localhost/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:passwd@localhost/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',)]

您注意到,两个都将使用TCP连接(我知道这是因为主机名后面的端口号)。另一方面:

>>> engine = create_engine( "mysql+pymysql://sylvain:passwd@localhost/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:passwd@localhost/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',)]

主机名

后没有端口:这是UNIX套接字。
在我的设置中(我使用mysql-python),仅使用127.0.0.1代替了MySQL SQLAlchemy url中的localhost。我正完全用于该情况的完整URL(具有本地端口3307的隧道)是:

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

我正在使用SQLAlchemy 1.0.5,但我想这没什么大不了...

这对我有用:

import pandas as pd import pymysql from sqlalchemy import create_engine cnx = create_engine('mysql+pymysql://<username>:<password>@<host>/<dbname>') df = pd.read_sql('SELECT * FROM <table_name>', cnx) #read the entire table


7
投票
在我的设置中(我使用mysql-python),仅使用127.0.0.1代替了MySQL SQLAlchemy url中的localhost。我正完全用于该情况的完整URL(具有本地端口3307的隧道)是:

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


0
投票
这对我有用:

import pandas as pd import pymysql from sqlalchemy import create_engine cnx = create_engine('mysql+pymysql://<username>:<password>@<host>/<dbname>') df = pd.read_sql('SELECT * FROM <table_name>', cnx) #read the entire table

© www.soinside.com 2019 - 2024. All rights reserved.