通过 Paramiko SSH 的 SQLAlchemy

SQLAlchemy through Paramiko SSH

我在服务器上有一个数据库,我需要通过 SSH 访问它。现在我通过命令行获取数据来处理数据库。

import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname='XX.XX.XX', username='user', password='pass', port = YYY)
query = "mysql -u " + username_sql + " -p" + password_sql +" dbb -e \"" + sql_query + "\""
ssh.exec_command(query.decode('string_escape'))
ssh.close()

有没有一种方法可以使用 SQLAlchemy 来提高效率,这样我就可以直接使用 pandas DataFrames?

from sqlalchemy import create_engine
engine = create_engine(
       "mysql://username_sql:password_sql@localhost/dbb")

最简单的方法是 运行 到远程主机上 mysql 端口的 SSH 隧道。 For example:

ssh -f user@XX.XX.XX.XX -L 3307:mysql1.example.com:3306 -N

然后使用 SQLAlchemy 在本地连接:

engine = create_engine("mysql://username_sql:password_sql@localhost:3307/dbb")

如果你真的想使用 paramiko,请尝试 this demo code in the paramiko repo or the sshtunnel module. The ssh command might be the easiest method though.. and you can use autossh 在隧道关闭时重新启动隧道。

您可以按如下方式使用 SSHTunnel 库:

from sshtunnel import SSHTunnelForwarder #Run pip install sshtunnel
from sqlalchemy.orm import sessionmaker #Run pip install sqlalchemy

with SSHTunnelForwarder(
    ('10.160.1.24', 22), #Remote server IP and SSH port
    ssh_username = "<usr>",
    ssh_password = "<pwd>",
    remote_bind_address=('127.0.0.1', 5432)
    ) as server:

    server.start() #start ssh sever
    print 'Server connected via SSH'

    #connect to PostgreSQL
    local_port = str(server.local_bind_port)
    engine = create_engine('postgresql://<db_user>:<db_pwd>@127.0.0.1:' + local_port +'/<db_name>')

    Session = sessionmaker(bind=engine)
    session = Session()

    print 'Database session created'

    #test data retrieval
    test = session.execute("SELECT * FROM <table_name>")

只需将服务器的(主机,端口)与postgres交换即可:

from sshtunnel import SSHTunnelForwarder #Run pip install sshtunnel

server = SSHTunnelForwarder(
    (<'your host'>, <host port>),
    ssh_username=<"os remote username">,
    ssh_pkey=<'path/to/key.pem'>,  # or ssh_password.
    remote_bind_address=(<'postgres db host'>, <'postgres db port'>))

server.start()

connection_data = 'postgresql://{user}:{password}@{host}:{port}/{db}'.format(user=<'postgres user'>,
                                                                             password=<'postgres password'>,
                                                                             host=server.local_bind_host,
                                                                             port=server.local_bind_port,
                                                                             db=<'postgres db name'>)

engine = create_engine(connection_data)

# Do your queries

server.stop()

以防有人对通过 SSH 连接到远程 Postgresql 数据库感兴趣并希望将数据加载到 pandas DataFrame 方法如下。

假设我们在远程服务器上安装了一个postgresql数据库,我们可以通过以下参数ssh到它。

SSH 参数:

  • 服务器IP:10.0.0.101
  • SSH 端口:22SSH 的默认端口
  • 用户名:my_username
  • 密码:my_password

数据库参数:

  • 端口:5432postgresql 默认端口
  • 数据库名称:db
  • 数据库用户:postgres_user默认用户名是postgres
  • 数据库密码:postgres_pswd默认密码为空字符串
  • Table 我们的数据:MY_TABLE

现在,我们要连接到这个数据库并将数据加载到 pandas DataFrame 中:

from sshtunnel import SSHTunnelForwarder
from sqlalchemy import create_engine
import pandas as pd

server = SSHTunnelForwarder(
    ('10.0.0.101', 22),
    ssh_username="my_username",
    ssh_password="my_password",
    remote_bind_address=('127.0.0.1', 5432)
    )

server.start()
local_port = str(server.local_bind_port)
engine = create_engine('postgresql://{}:{}@{}:{}/{}'.format("postgres_user", "postgres_pswd", "127.0.0.1", local_port, "db"))

dataDF = pd.read_sql("SELECT * FROM \"{}\";".format("MY_TABLE"), engine)

server.stop()

我将使用非 postgresql 数据库搭载 @Matin Kh - MySQL 并使用 Pythonanywhere.com。 此代码将采用 table 并将其转换为 excel 文件。

import sshtunnel
import sqlalchemy
import pymysql
import pandas as pd
from pandas import ExcelWriter
import datetime as dt
from sshtunnel import SSHTunnelForwarder

server = SSHTunnelForwarder(
    ('ssh.pythonanywhere.com'),
    ssh_username='username', 
    ssh_password='password',
    remote_bind_address=('username.mysql.pythonanywhere-services.com', 3306) ) 

server.start()
local_port = str(server.local_bind_port)
db = 'username$database'
engine = sqlalchemy.create_engine(f'mysql+pymysql://username:password@127.0.0.1:{local_port}/{db}')

print('Engine Created')

df_read = pd.read_sql_table('tablename',engine)
print('Grabbed Table')
writer = ExcelWriter('excelfile.xlsx')
print('writer created')
df_read.to_excel(writer,'8==D') # '8==D' specifies sheet
print('df to excel')
writer.save()
print('saved')
server.stop()