使用 SSH 隧道从远程服务器上的 MariaDB 读取数据
Read data from MariaDB on remote server with SSH tunnel
以下设置:在我的本地 Windows 机器上,我 运行 Spyder 和 Python 3.5。此外,我有一个带有 MariaDB 的远程 Ubuntu 服务器。我想要做的是使用 SSH 隧道和 sqlalchemy 将数据库中的数据加载到 Spyder。
我正在寻找的两个解决方案是:
(i) 将 PuTTY 用于 SSH 隧道到服务器的解释 here 然后在 Spyder 中:
import mysql.connector
from sqlalchemy import create_engine
import pandas as pd
engine = create_engine('mysql+mysqlconnector://un_db:pw_db@127.0.0.1/db')
dbconn = engine.connect()
rslt = dbconn.execute("SELECT * FROM table WHERE col1=x AND col2=y;")
df = pd.DataFrame(rslt.fetchall())
df.columns = rslt.keys()
这在性能方面效果很好,但我已经打开 PuTTY 并建立 SSH 隧道作为过程中的额外步骤。
(ii) 使用包 sshtunnel,从而避免 PuTTY 额外步骤:
from sshtunnel import SSHTunnelForwarder
import mysql.connector
from sqlalchemy import create_engine
import pandas as pd
server = SSHTunnelForwarder(
(hostname, 22),
ssh_username=un_server, \
ssh_password=pw_server,
remote_bind_address=('127.0.0.1', 3306))
server.start()
engine = create_engine('mysql+mysqlconnector://un_db:pw_db@127.0.0.1:' \
+ str(server.local_bind_port) + '/db')
dbconn = engine.connect()
rslt = dbconn.execute("SELECT * FROM table WHERE col1=x AND col2=y;")
df = pd.DataFrame(rslt.fetchall())
df.columns = rslt.keys()
建立 SSH 隧道一切正常(我认为)但是当我执行查询时,Spyder 中的 IPython 控制台挂起。
问题:为什么我的用例适用于 PuTTY 但不适用于包 sshtunnel?通过 PuTTY 的 SSH 隧道和通过包 sshtunnel 的 SSH 隧道之间有区别吗?
你有两个相似的解决方案。
(i) 在这种情况下,您创建一个转发过程。 (不是 python 进程)
(ii) 在这种情况下 server.start()
启动新的 python 转发线程。这个线程做类似的工作。但它是 python 个线程,线程将一直工作直到它停止。也许这就是您遇到问题的原因。
根据问题,我可以提出三个解决方案。
您可以使用sshtunnel
创建转发过程,如PuTTY
。来自自述文件:python -m sshtunnel -U username -P password -L :3306 -R 127.0.0.1:3306 -p 22 localhost
您可以只使用 server.stop()
来停止 sshtunnel
转发线程。
也可以使用with
语句语法自动停止
(sshtunnel#example-2)
我将驱动程序从 mysql.connector 切换到 MySQLdb,新的解决方案 (ii) 现在也有效:
from sshtunnel import SSHTunnelForwarder
import MySQLdb as mdb
import pandas as pd
server = SSHTunnelForwarder(
(hostname, 22),
ssh_username=un_server, \
ssh_password=pw_server,
remote_bind_address=('127.0.0.1', 3306))
server.start()
con = mdb.connect('127.0.0.1', un_db, pw_db, port=server.local_bind_port)
df = pd.read_sql("SELECT * FROM table WHERE col1=x AND col2=y", con)
con.close()
server.stop()
以下设置:在我的本地 Windows 机器上,我 运行 Spyder 和 Python 3.5。此外,我有一个带有 MariaDB 的远程 Ubuntu 服务器。我想要做的是使用 SSH 隧道和 sqlalchemy 将数据库中的数据加载到 Spyder。
我正在寻找的两个解决方案是:
(i) 将 PuTTY 用于 SSH 隧道到服务器的解释 here 然后在 Spyder 中:
import mysql.connector
from sqlalchemy import create_engine
import pandas as pd
engine = create_engine('mysql+mysqlconnector://un_db:pw_db@127.0.0.1/db')
dbconn = engine.connect()
rslt = dbconn.execute("SELECT * FROM table WHERE col1=x AND col2=y;")
df = pd.DataFrame(rslt.fetchall())
df.columns = rslt.keys()
这在性能方面效果很好,但我已经打开 PuTTY 并建立 SSH 隧道作为过程中的额外步骤。
(ii) 使用包 sshtunnel,从而避免 PuTTY 额外步骤:
from sshtunnel import SSHTunnelForwarder
import mysql.connector
from sqlalchemy import create_engine
import pandas as pd
server = SSHTunnelForwarder(
(hostname, 22),
ssh_username=un_server, \
ssh_password=pw_server,
remote_bind_address=('127.0.0.1', 3306))
server.start()
engine = create_engine('mysql+mysqlconnector://un_db:pw_db@127.0.0.1:' \
+ str(server.local_bind_port) + '/db')
dbconn = engine.connect()
rslt = dbconn.execute("SELECT * FROM table WHERE col1=x AND col2=y;")
df = pd.DataFrame(rslt.fetchall())
df.columns = rslt.keys()
建立 SSH 隧道一切正常(我认为)但是当我执行查询时,Spyder 中的 IPython 控制台挂起。
问题:为什么我的用例适用于 PuTTY 但不适用于包 sshtunnel?通过 PuTTY 的 SSH 隧道和通过包 sshtunnel 的 SSH 隧道之间有区别吗?
你有两个相似的解决方案。
(i) 在这种情况下,您创建一个转发过程。 (不是 python 进程)
(ii) 在这种情况下 server.start()
启动新的 python 转发线程。这个线程做类似的工作。但它是 python 个线程,线程将一直工作直到它停止。也许这就是您遇到问题的原因。
根据问题,我可以提出三个解决方案。
您可以使用
sshtunnel
创建转发过程,如PuTTY
。来自自述文件:python -m sshtunnel -U username -P password -L :3306 -R 127.0.0.1:3306 -p 22 localhost
您可以只使用
server.stop()
来停止sshtunnel
转发线程。也可以使用
with
语句语法自动停止 (sshtunnel#example-2)
我将驱动程序从 mysql.connector 切换到 MySQLdb,新的解决方案 (ii) 现在也有效:
from sshtunnel import SSHTunnelForwarder
import MySQLdb as mdb
import pandas as pd
server = SSHTunnelForwarder(
(hostname, 22),
ssh_username=un_server, \
ssh_password=pw_server,
remote_bind_address=('127.0.0.1', 3306))
server.start()
con = mdb.connect('127.0.0.1', un_db, pw_db, port=server.local_bind_port)
df = pd.read_sql("SELECT * FROM table WHERE col1=x AND col2=y", con)
con.close()
server.stop()