создание пула выдает ошибку соединения, если ранее соединение не было создано - PullRequest
0 голосов
/ 26 января 2020

Я использую sqlalchemy ORM и драйвер py mysql для подключения к БД, я обнаружил поведение, которое я не понимаю,

import os
import pymysql
from sqlalchemy.orm import Session
from sqlalchemy import create_engine, exc
import sqlalchemy.pool as pool
from sqlalchemy import select


class DataConnector(object):
    """docstring for DataConnector"""
    def __init__(self, auths=None):
        super(DataConnector, self).__init__()
        self._auths = auths or {}
        for key in ["user", "password", "host"]:
            if key not in self._auths:
                value = os.getenv("MYSQL_{0}".format(key.upper()))
                if not value:
                    raise KeyError("Missing {0} key".format(key))
                self._auths[key] = value
        self._dbName = None

    def _connector(self):
        return pymysql.connections.Connection(**self._auths)

    @staticmethod
    def get_pool(cls):
        """Gets the pool for mysql connection.
        """
        # TODO: make pool size confurable using ability to set through property
        return pool.QueuePool(cls._connector, max_overflow=10, pool_size=5)

    @property
    def dbname(self):
        return self._dbname

    @dbname.setter
    def dbname(self, dbname):
        self._dbname = dbname
        self._auths["database"] = self._dbname

    def connect(self):
        if "database" not in self._auths or not self._auths["database"]:
            raise ValueError("Database is not set.")
        try:
            pool = self.get_pool(self)
            connection = create_engine('mysql+pymysql://', pool=pool)
            return connection
        except Exception as er:
            print("Getting error: {0}".format(er))


if __name__ == '__main__':
    # for testing
    connector = DataConnector()
    connector.dbname = "exampledb"
    connection = connector.connect()
    print(connection.table_names()) << Errors at this point

, если используется подход пула, код выше выдает ошибку , если предыдущее успешное соединение не существует.

Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/pymysql/connections.py", line 583, in connect
    **kwargs)
  File "/usr/local/Cellar/python/3.7.4_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/socket.py", line 727, in create_connection
    raise err
  File "/usr/local/Cellar/python/3.7.4_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/socket.py", line 716, in create_connection
    sock.connect(sa)
OSError: [Errno -536870212] Unknown error: -536870212

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 2275, in _wrap_pool_connect
    return fn()
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/pool/base.py", line 363, in connect
    return _ConnectionFairy._checkout(self)
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/pool/base.py", line 760, in _checkout
    fairy = _ConnectionRecord.checkout(pool)
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/pool/base.py", line 492, in checkout
    rec = pool._do_get()
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/pool/impl.py", line 139, in _do_get
    self._dec_overflow()
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/util/langhelpers.py", line 68, in __exit__
    compat.reraise(exc_type, exc_value, exc_tb)
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/util/compat.py", line 153, in reraise
    raise value
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/pool/impl.py", line 136, in _do_get
    return self._create_connection()
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/pool/base.py", line 308, in _create_connection
    return _ConnectionRecord(self)
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/pool/base.py", line 437, in __init__
    self.__connect(first_connect_check=True)
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/pool/base.py", line 639, in __connect
    connection = pool._invoke_creator(self)
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/pool/base.py", line 264, in <lambda>
    return lambda crec: creator()
  File "connect.py", line 22, in _connector
    return pymysql.connections.Connection(**self._auths)
  File "/usr/local/lib/python3.7/site-packages/pymysql/connections.py", line 325, in __init__
    self.connect()
  File "/usr/local/lib/python3.7/site-packages/pymysql/connections.py", line 630, in connect
    raise exc
pymysql.err.OperationalError: (2003, "Can't connect to MySQL server on 'mysqlhost' ([Errno -536870212] Unknown error: -536870212)")

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "connect.py", line 56, in <module>
    print(connection.table_names())
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 2253, in table_names
    with self._optional_conn_ctx_manager(connection) as conn:
  File "/usr/local/Cellar/python/3.7.4_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/contextlib.py", line 112, in __enter__
    return next(self.gen)
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 2037, in _optional_conn_ctx_manager
    with self._contextual_connect() as conn:
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 2239, in _contextual_connect
    self._wrap_pool_connect(self.pool.connect, None),
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 2279, in _wrap_pool_connect
    e, dialect, self
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1544, in _handle_dbapi_exception_noconnection
    util.raise_from_cause(sqlalchemy_exception, exc_info)
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/util/compat.py", line 398, in raise_from_cause
    reraise(type(exception), exception, tb=exc_tb, cause=cause)
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/util/compat.py", line 152, in reraise
    raise value.with_traceback(tb)
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 2275, in _wrap_pool_connect
    return fn()
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/pool/base.py", line 363, in connect
    return _ConnectionFairy._checkout(self)
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/pool/base.py", line 760, in _checkout
    fairy = _ConnectionRecord.checkout(pool)
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/pool/base.py", line 492, in checkout
    rec = pool._do_get()
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/pool/impl.py", line 139, in _do_get
    self._dec_overflow()
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/util/langhelpers.py", line 68, in __exit__
    compat.reraise(exc_type, exc_value, exc_tb)
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/util/compat.py", line 153, in reraise
    raise value
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/pool/impl.py", line 136, in _do_get
    return self._create_connection()
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/pool/base.py", line 308, in _create_connection
    return _ConnectionRecord(self)
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/pool/base.py", line 437, in __init__
    self.__connect(first_connect_check=True)
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/pool/base.py", line 639, in __connect
    connection = pool._invoke_creator(self)
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/pool/base.py", line 264, in <lambda>
    return lambda crec: creator()
  File "connect.py", line 22, in _connector
    return pymysql.connections.Connection(**self._auths)
  File "/usr/local/lib/python3.7/site-packages/pymysql/connections.py", line 325, in __init__
    self.connect()
  File "/usr/local/lib/python3.7/site-packages/pymysql/connections.py", line 630, in connect
    raise exc
sqlalchemy.exc.OperationalError: (pymysql.err.OperationalError) (2003, "Can't connect to MySQL server on 'mysqlhost' ([Errno -536870212] Unknown error: -536870212)")
(Background on this error at: http://sqlalche.me/e/e3q8)

, но как только я создаю успешное соединение с простым:

connection = create_engine('mysql+pymysql://userame:password@mysqlhost/testdb')

, попробуйте

    connector = DataConnector()
    connector.dbname = "exampledb"
    connection = connector.connect()
    print(connection.table_names())

работает , почему так. вещи, которые я не хочу устанавливать для имени пользователя и пароля с помощью db на create_engine напрямую. или я делаю что-то не так и вообще не понял, как объединить: /

...