Менеджер контекста sshTunnelForwarder зависает - PullRequest
0 голосов
/ 10 марта 2020

Трудно понять, почему эти два куска кода не работают одинаково. Версия не-контекстного менеджера работает отлично (я подключаюсь к mysql, работающему на экземпляре Ubuntu EC2, порт 3306 НЕ открыт, следовательно, туннель), а версия диспетчера контекста получает отказавший менеджер соединения или просто зависает. Мои учетные данные хороши, проверены различными способами, я на 99% уверен, что это менеджер контекста, но я также не могу получить отладочную информацию из него.

import pandas as pd

from sshtunnel import SSHTunnelForwarder
from sqlalchemy import create_engine

# server
remote_host = 'www.njbuswatcher.com'
ssh_username = 'ubuntu'
private_key = 'buswatcher_2020.pem'

# database
dbuser='buswatcher'
dbpwd='' # redacted
dbname='buses'

# period SQL definitions
today = """CURDATE()"""
yesterday = """DATE_ADD(CURDATE(), INTERVAL -1 DAY)"""


def query(q):

    server = SSHTunnelForwarder(
        (remote_host, 22),
        ssh_username=ssh_username,
        ssh_private_key=private_key,
        remote_bind_address=('127.0.0.1', 3306)
    )
    server.start()
    engine = create_engine('mysql+pymysql://{}:{}@127.0.0.1:{}/{}'.format(dbuser,dbpwd,server.local_bind_port,dbname))
    conn = engine.connect()

    results = pd.read_sql_query(q, conn)

    engine.dispose()

    return results

# run query
q = """
    SELECT * from trio_log LIMIT 5;
    """

query(q)

И версия обработчика контекста

import pandas as pd

from sshtunnel import SSHTunnelForwarder
from sqlalchemy import create_engine

# server
remote_host = 'www.njbuswatcher.com'
ssh_username = 'ubuntu'
private_key = 'buswatcher_2020.pem'

# database
dbuser='buswatcher'
dbpwd='' # redacted
dbname='buses'


def query(q):
    with SSHTunnelForwarder(
        (remote_host, 22),
        ssh_username=ssh_username,
        ssh_private_key=private_key,
        remote_bind_address=('127.0.0.1', 3306)
        ) as server:
        engine = create_engine('mysql+pymysql://{}:{}@127.0.0.1/{}'.format(dbuser,dbpwd,dbname))
        conn = engine.connect()
        return pd.read_sql_query(q, conn)

# test
q = """
    SELECT * FROM trip_log LIMIT 5;
"""
query(q)

Я знаю, что я специально не привязываюсь к случайному порту #, выбранному здесь, как в предыдущей версии, но я предположил, что менеджер контекста обрабатывает это?

Добавление случайного порта к URL-адрес базы данных просто приводит к зависанию.

def query(q):
    with SSHTunnelForwarder(
        (remote_host, 22),
        ssh_username=ssh_username,
        ssh_private_key=private_key,
        remote_bind_address=('127.0.0.1', 3306)
        ) as server:
        db_connection_url = 'mysql+pymysql://{}:{}@127.0.0.1:{}/{}'.format(dbuser,dbpwd,server.local_bind_port,dbname)
        print (db_connection_url)
        engine = create_engine(db_connection_url)
        conn = engine.connect()
        return pd.read_sql_query(q, conn)

Привязка вручную к указанному c локальному порту также приводит к зависанию:


def query(q):
    with SSHTunnelForwarder(
        (remote_host, 22),
        ssh_username=ssh_username,
        ssh_private_key=private_key,
        remote_bind_address=('127.0.0.1', 3306),
        local_bind_address = ('127.0.0.1', 3306)
        ) as server:
        db_connection_url = 'mysql+pymysql://{}:{}@127.0.0.1:3306/{}'.format(dbuser,dbpwd,dbname)
        print (db_connection_url)
        engine = create_engine(db_connection_url)
        conn = engine.connect()
        return pd.read_sql_query(q, conn)

FWIW, у меня нет ничего локально прослушивающего на 3306

...