【问题标题】:SQLAlchemy through Paramiko SSH通过 Paramiko SSH 实现 SQLAlchemy
【发布时间】:2020-05-19 10:34:18
【问题描述】:

我在需要通过 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")

【问题讨论】:

    标签: python mysql ssh sqlalchemy paramiko


    【解决方案1】:

    如果有人有兴趣通过 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默认密码为空字符串
    • 我们的数据表: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()
    

    【讨论】:

      【解决方案2】:

      最简单的方法是运行 SSH 隧道到远程主机上的 mysql 端口。 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 reposshtunnel 模块。 ssh 命令可能是最简单的方法。如果隧道出现故障,您可以使用autossh 重新启动隧道。

      【讨论】:

        【解决方案3】:

        您可以按如下方式使用 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>")
        

        【讨论】:

          【解决方案4】:

          只需将服务器的(主机、端口)与 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()
          

          【讨论】:

            【解决方案5】:

            我将使用非 postgresql 数据库 - MySQL 并使用 Pythonanywhere.com 搭载 @Matin Kh。 此代码将获取一个表格并将其转换为 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()
            

            【讨论】: