Как заставить Flask SQLAlchemy повторно использовать подключения к БД?

Я не могу заставить приложение Flask закрыть или повторно использовать соединения с БД. Я использую PostgreSQL 9.1.3 и

Flask==0.8
Flask-SQLAlchemy==0.16
psycopg2==2.4.5

. По мере выполнения моего набора тестов количество открытых соединений увеличивается до тех пор, пока не достигнет 20 (настройка max_connectionsв postgresql.conf), затем Я вижу:

OperationalError: (OperationalError) FATAL:  sorry, too many clients already
 None None

Я сократил код до точки, где он просто вызывает create_allи drop_all(но не выдает никакого sql, так как нет моделей).

В журналах я вижу, что соединения проверяются и удаляются:

DEBUG:sqlalchemy.pool.QueuePool:Connection  checked out from pool
DEBUG:sqlalchemy.pool.QueuePool:Connection  being returned to pool
WARNING:root:impl   <-------- That's the test running
DEBUG:sqlalchemy.pool.QueuePool:Connection  checked out from pool
DEBUG:sqlalchemy.pool.QueuePool:Connection  being returned to pool

Для каждого тестового прогона адрес соединения (часть «объект соединения в xyz») отличается. Я подозреваю, что это как-то связано с проблемой, но я не уверен, как исследовать дальше.

Код ниже воспроизводит проблему в новой версии:

from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
from unittest import TestCase

import logging
logging.basicConfig(level=logging.DEBUG)
logging.getLogger('sqlalchemy.pool').setLevel(logging.DEBUG)
logging.getLogger('sqlalchemy.engine').setLevel(logging.DEBUG)
logging.getLogger('sqlalchemy.dialects').setLevel(logging.DEBUG)
logging.getLogger('sqlalchemy.orm').setLevel(logging.DEBUG)


db = SQLAlchemy()

def create_app(config=None):
    app = Flask(__name__)
    app.config.from_object(config)
    db.init_app(app)
    return app


class AppTestCase(TestCase):
    SQLALCHEMY_DATABASE_URI = "postgresql://localhost/cx_test"
    TESTING = True

    def create_app(self):
        return create_app(self)

    def setUp(self):
        self.app = self.create_app()
        self.client = self.app.test_client()
        self._ctx = self.app.test_request_context()
        self._ctx.push()
        db.create_all()

    def tearDown(self):
        db.session.remove()
        db.drop_all()
        self._ctx.pop()


class TestModel(AppTestCase):
    def impl(self):
        logging.warn("impl")
        pass

    def test_01(self):
        self.impl()

    def test_02(self):
        self.impl()

    def test_03(self):
        self.impl()

    def test_04(self):
        self.impl()

    def test_05(self):
        self.impl()

    def test_06(self):
        self.impl()

    def test_07(self):
        self.impl()

    def test_08(self):
        self.impl()

    def test_09(self):
        self.impl()

    def test_10(self):
        self.impl()

    def test_11(self):
        self.impl()

    def test_12(self):
        self.impl()

    def test_13(self):
        self.impl()

    def test_14(self):
        self.impl()

    def test_15(self):
        self.impl()

    def test_16(self):
        self.impl()

    def test_17(self):
        self.impl()

    def test_18(self):
        self.impl()

    def test_19(self):
        self.impl()



if __name__ == "__main__":
    import unittest
    unittest.main()

Это первый раз, когда я использовал фабрики приложений в flask, и я частично скопировал этот код из документации Flask-SQLAlchemy. Другое ПОВ этих документах упоминается, что использование базы данных в неправильном контексте приведет к утечке соединений — может быть, я неправильно выполняю инициализацию?

21
задан Tom Dunham 16 May 2012 в 07:22
поделиться