Как избежать SQLAlchemy Timeout Error при выполнении нескольких потоков - PullRequest
0 голосов
/ 07 марта 2020

Ну, у меня возникли небольшие проблемы с поиском решения этой проблемы. Для этого проекта я использую Python 2.7, PostgreSQL, SQLAlchemy, Pandas, Matplotlib, среди других библиотек и как IDE, pycharm. У меня есть этот маршрут, который следует следующей структуре. GUI Frame -> Threads -> Instruments Обработка или чтение потоков или процедура контроля. И пример этой структуры в Код 1 . Целью потоков является бесконечное поддержание и восстановление процесса каждый раз, когда он терпит неудачу. Эти процессы и потоки создают with session_scope() as s: с помощью диспетчера контекста в области сеанса, поэтому я обязательно завершаю соединение после его использования, пример этого приведен в Код 2 . Проблема заключается в том, что когда код работает примерно 10 минут, он начинает выдавать TimeoutError: QueuePool limit of size 5 overflow 10 reached, connection timed out, timeout 5 (Background on this error at: http://sqlalche.me/e/3o7r), полный код - Код 3 .

Самое смешное, что если я продолжаю запускать скрипт, ошибка будет согласована только в одной строке: created_file = s.query(neo_file).filter(neo_file.id == 1).all(). Эта строка является частью подпотока, в примерном потоке Code 1, который я разместил, этот основной поток отличается от другого, потому что остальные потоки управляют процессом, но для этого инструмента мне пришлось использовать потоки.

Я пытался ограничить pool_timeout 5, но он продолжает делать то же самое. И я думаю, что увеличение переполнения и размера пула здесь не решает проблемы. Есть хоть какие то, что я делаю не так? Если вам нужно больше кода из проекта, просто спросите.

Код 1: Пример одного из основных потоков

class wibs_neo_thread(Thread):
    def __init__(self):
        Thread.__init__(self)

        config = ConfigParser()
        config.read(configuration_path)
        self.directory = config.get('INSTRUMENT DIRECTORIES', 'wibs_directory')

        self.name = 'wibs_neo_process'
        self.log = logger().get_logger(self.name)
        self.is_running = True
        self.daemon = True
        self.start()

    def run(self):
        status = True
        while self.is_running:
            if status == True:
                y = wibs_monitor_thread(self.directory, self.log)
                x = wibs_read_thread(self.log)
                with session_scope() as s:
                    s.query(process).filter(process.process_name == x.name).update({process.status: 'INITIATING'})
                    #s.commit()
                status = False
                y.start()

                if y.is_alive() == True:
                    x.start()

                time.sleep(1)
                while self.is_running:
                    if x.is_alive() == True and y.is_alive() == True:
                        with session_scope() as s:
                            s.query(process).filter(process.process_name == x.name).update({process.status: 'RUNNING'})
                            #s.commit()
                        time.sleep(1)
                    elif x.is_alive() == False or y.is_alive() == False:
                        status = True
                        with session_scope() as s:
                            s.query(process).filter(process.process_name == x.name).update(
                                {process.status: 'RESTARTING'})
                            #s.commit()
                        time.sleep(1)
                        break

Код 2: Код области сеанса

@contextmanager
def session_scope(): #Create session for queries.
    session = Session()
    try:
        yield session
        session.commit()
    except Exception:
        session.rollback()
        raise
    finally:
        session.close()

Код 3: ошибка тайм-аута

Exception in thread wibs_neo_process:
Traceback (most recent call last):
  File "C:\Python27\lib\threading.py", line 801, in __bootstrap_inner
    self.run()
  File "C:\Users\naxso\PycharmProjects\ACAS\Main\Process\threads.py", line 202, in run
    created_file = s.query(neo_file).filter(neo_file.id == 1).all()
  File "C:\Python27\lib\site-packages\sqlalchemy\orm\query.py", line 3233, in all
    return list(self)
  File "C:\Python27\lib\site-packages\sqlalchemy\orm\query.py", line 3389, in __iter__
    return self._execute_and_instances(context)
  File "C:\Python27\lib\site-packages\sqlalchemy\orm\query.py", line 3411, in _execute_and_instances
    querycontext, self._connection_from_session, close_with_result=True
  File "C:\Python27\lib\site-packages\sqlalchemy\orm\query.py", line 3426, in _get_bind_args
    mapper=self._bind_mapper(), clause=querycontext.statement, **kw
  File "C:\Python27\lib\site-packages\sqlalchemy\orm\query.py", line 3404, in _connection_from_session
    conn = self.session.connection(**kw)
  File "C:\Python27\lib\site-packages\sqlalchemy\orm\session.py", line 1133, in connection
    execution_options=execution_options,
  File "C:\Python27\lib\site-packages\sqlalchemy\orm\session.py", line 1139, in _connection_for_bind
    engine, execution_options
  File "C:\Python27\lib\site-packages\sqlalchemy\orm\session.py", line 432, in _connection_for_bind
    conn = bind._contextual_connect()
  File "C:\Python27\lib\site-packages\sqlalchemy\engine\base.py", line 2242, in _contextual_connect
    self._wrap_pool_connect(self.pool.connect, None),
  File "C:\Python27\lib\site-packages\sqlalchemy\engine\base.py", line 2276, in _wrap_pool_connect
    return fn()
  File "C:\Python27\lib\site-packages\sqlalchemy\pool\base.py", line 363, in connect
    return _ConnectionFairy._checkout(self)
  File "C:\Python27\lib\site-packages\sqlalchemy\pool\base.py", line 773, in _checkout
    fairy = _ConnectionRecord.checkout(pool)
  File "C:\Python27\lib\site-packages\sqlalchemy\pool\base.py", line 492, in checkout
    rec = pool._do_get()
  File "C:\Python27\lib\site-packages\sqlalchemy\pool\impl.py", line 131, in _do_get
    code="3o7r",
TimeoutError: QueuePool limit of size 5 overflow 10 reached, connection timed out, timeout 5 (Background on this error at: http://sqlalche.me/e/3o7r)
...