使用flasksqlalchmey model类查询导致数据库会话泄漏

2024-06-28 11:31:13 发布

您现在位置:Python中文网/ 问答频道 /正文

现在很沮丧。我遇到这样一个问题:使用类类型(即User.query.filter(...))或类本身的实例(即u = User(...)return u.query.filter(...).first())执行DB查询时,每次都会创建一个新会话。你知道吗

最后,当我尝试执行add/commit时,我得到了一个谚语:

InvalidRequestError: Object '<Loadable at 0x1b02f90>' is already attached to session '1' (this is '4')

值得一提的是,我发现由于以下原因,新的会话会继续创建:

app/_ _ init _ _.py:

@login_manager.user_loader

def load_user(id):

from app.users.models import User
return User.query.get(int(id))

所有页面请求都会调用load_user(),每次它被命中时,我就有一个新会话。我可以自信地说,因为我在
中设置了断点 /lib/python2.7/site-packages/sqlalchemy/orm/session.py
创建和销毁会话。我希望这是一件小事,能指出我对这些东西如何分配的严重误解。一开始我满头的头发,但我已经为这件事挠头很久了,现在我要秃头了。请保存我的头发。你知道吗

因此,接受Miguel的建议并在
中的会话创建位置设置断点 lib/python2.7/site-packages/flask_sqlalchemy/__init__.py(137)__init__()
我可以看到这是我编写的一个函数的结果,该函数逐个加载它在给定目录中看到的所有模块。堆栈跟踪如下:

  /home/robert/snak2/run.py(1)<module>()
-> from app import app
  /home/robert/snak2/app/__init__.py(39)<module>()
-> load_all_modules_from_dir('app')
  /home/robert/snak2/app/utils.py(87)load_all_modules_from_dir()
-> ).load_module(full_package_name)
  /usr/lib64/python2.7/pkgutil.py(246)load_module()
-> mod = imp.load_module(fullname, self.file, self.filename, self.etc)
  /home/robert/snak2/app/account/__init__.py(17)<module>()
-> mod.mod_register(MODNAME, MODCAT, NAME, LINK, AUTHOR, DESC, ICON, NAVS)
  /home/robert/snak2/app/loader.py(159)mod_register()
**-> mod = Loadable.query.filter(Loadable.modname == modname).first()(**)**
  /home/robert/snak2/env/lib/python2.7/site-packages/flask_sqlalchemy/__init__.py(429)__get__()
-> return type.query_class(mapper, session=self.sa.session())
  /home/robert/snak2/env/lib/python2.7/site-packages/sqlalchemy/orm/scoping.py(70)__call__()
-> return self.registry()
  /home/robert/snak2/env/lib/python2.7/site-packages/sqlalchemy/util/_collections.py(864)__call__()
-> return self.registry.setdefault(key, self.createfunc())
> /home/robert/snak2/env/lib/python2.7/site-packages/flask_sqlalchemy/__init__.py(137)__init__()
-> self.app = db.get_app()

根据Miguel在kick a$$教程中提供的信息,我认为是堆栈中用(**)表示的行实际导致了新会话的创建(并持久化)。但如何让它消失呢?你知道吗


Tags: pyselfapphomereturnsqlalchemyinitlib