V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
bg7lgb
V2EX  ›  Python

flask 中使用连接池和 app_context 求助

  •  
  •   bg7lgb · 2015-10-20 14:03:45 +08:00 · 5704 次点击
    这是一个创建于 3326 天前的主题,其中的信息可能已经有所发展或是发生改变。
    v2ex 的处女贴,奉献给 flask 。

    刚开始学 flask ,还没时间看 sqlalchemy 。

    python2.7 , flask 0.10.1 。数据库是 oracle ,使用了 cx_Oracle 作为驱动。

    按以往的经验,在创建了一个连接池,每次有请求进行时从池子中获取获取一个 connection ,访问 db 后,把 connection release 回池中。

    问题:
    1 、看打出来的日志,只初始化了一次连接池,结果出来两次“ connect db ”。
    2 、对于 app_context 的使用还是很困惑。
    何时需要 app_context , app_context 是否是唯一的?
    如何把池的信息附加到 app_context ,使在每次的 request 时都可以正确获取到。

    附件 1 : db.py
    import cx_Oracle as cxo
    from flask import current_app

    try:
    from flask import _app_ctx_stack as stack
    except ImportError:
    from flask import _request_ctx_stack as stack

    class OraDB(object):
    def __init__(self, app=None):
    self.app = app
    if app is not None:
    self.init_app(app)


    def init_app(self, app):
    if hasattr(app, 'teardown_appcontext'):
    app.teardown_appcontext(self.teardown)
    else:
    app.teardown_request(self.teardown)

    print 'connect db'
    ctx = app.app_context()
    ctx.push()

    self.pool = cxo.SessionPool(user=current_app.config['DBUSER'], \
    password=current_app.config['DBPASSWORD'], \
    dsn=current_app.config['DSN'], \
    min=current_app.config['MIN'], \
    max=current_app.config['MAX'], \
    increment=current_app.config['INCREMENT'], threaded=True)

    def connect(self):
    conn = self.pool.acquire()
    print 'in connect: pool id:', id(self.pool), ' conn id:', id(conn)
    return conn

    def teardown(self, exception):
    ctx = stack.top
    if hasattr(ctx, 'oradb'):
    print "teardown " + str(id(ctx.oradb))
    self.pool.release(ctx.oradb)

    @property
    def connection(self):
    ctx = stack.top
    if ctx is not None:
    if not hasattr(ctx, 'oradb'):
    ctx.oradb = self.connect()
    return ctx.oradb

    附件 2 : app.py
    from flask import Flask, current_app
    from db import OraDB

    app = Flask(__name__)
    app.config.from_pyfile('config.cfg')

    db = OraDB(app)

    @app.route('/')
    def index():
    cur = db.connection.cursor()
    cur.execute("select to_char(sysdate, 'yyyy-mm-dd hh24:mi:ss') from dual")
    rs = cur.fetchall()
    return rs[0][0]

    if __name__ == "__main__":
    app.run(debug=True)
    2 条回复    2015-11-01 01:46:28 +08:00
    bg7lgb
        1
    bg7lgb  
    OP
       2015-10-20 14:12:33 +08:00
    实际上数据库连接也是出现了两个,也就是产生了两个连接池。
    连接池的参数 : min 1 max 5 increment 1

    netstat -an|findstr "1521"
    TCP 192.1.4.78:5983 10.9.5.167:1521 ESTABLISHED
    TCP 192.1.4.78:6006 10.9.5.167:1521 ESTABLISHED
    tftk
        2
    tftk  
       2015-11-01 01:46:28 +08:00   ❤️ 1
    1. 把 DB Pool 放到 flask._app_ctx_stack 里,这样全局 能共享一个连接池。
    2. 需要的时候创建一个连接放到 flask.g 里,并在 teardown_request 里关闭这个连接。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1272 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 23:32 · PVG 07:32 · LAX 15:32 · JFK 18:32
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.