Трудно понять, почему эти два куска кода не работают одинаково. Версия не-контекстного менеджера работает отлично (я подключаюсь к 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