FlaskアプリでDB接続を閉じたり再利用したりできないようです。私はPostgreSQL9.1.3を使用しています
Flask==0.8
Flask-SQLAlchemy==0.16
psycopg2==2.4.5
max_connections
テストスイートを実行すると、開いている接続の数が20(の設定)に達するまで増加し、次のpostgresql.conf
ように表示されます。
OperationalError: (OperationalError) FATAL: sorry, too many clients already
None None
create_all
コードを、 andを呼び出すだけのポイントに減らしましたdrop_all
(ただし、モデルがないため、SQLを発行していません)。
ログに接続がチェックインおよびチェックアウトされているのがわかります。
DEBUG:sqlalchemy.pool.QueuePool:Connection <connection object at 0x101c1dff0; dsn: 'dbname=cx_test host=localhost', closed: 0> checked out from pool
DEBUG:sqlalchemy.pool.QueuePool:Connection <connection object at 0x101c1dff0; dsn: 'dbname=cx_test host=localhost', closed: 0> being returned to pool
WARNING:root:impl <-------- That's the test running
DEBUG:sqlalchemy.pool.QueuePool:Connection <connection object at 0x101c1dff0; dsn: 'dbname=cx_test host=localhost', closed: 0> checked out from pool
DEBUG:sqlalchemy.pool.QueuePool:Connection <connection object at 0x101c1dff0; dsn: 'dbname=cx_test host=localhost', closed: 0> being returned to pool
テストの実行ごとに、接続のアドレス(「xyzの接続オブジェクト」の部分)は異なります。これは問題と関係があるのではないかと思いますが、さらに調査する方法がわかりません。
以下のコードは、新しいvenvで問題を再現します。
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-SQLAlchemyのドキュメントからコピーしました。それ以外の場合、これらのドキュメントでは、間違ったコンテキストでデータベースを使用すると接続がリークする可能性があると述べています-おそらく私はinitを間違って行っていますか?