SQLAlchemy冻结应用程序

时间:2014-12-16 16:31:26

标签: python postgresql sqlalchemy

我在我的python命令行应用中使用SQLAlchemy。该应用程序基本上是读取一组URL并根据数据插入到postgreql数据库中。

在大约相同数量的插入(给予或采取一些)后,整个应用程序冻结。

看过python sqlalchemy + postgresql program freezes我假设我对SQLAlchemy Session做错了(虽然我没有使用drop_all(),这似乎是导致问题)。我尝试了几件事,但到目前为止他们没有任何影响。

欢迎任何提示或帮助。如果我将SQLAlchemy集成到我的应用程序中是不正确的,那么也欢迎指向正确行为的好例子。

我的代码如下:

设置sql炼金术基础:

from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()

创建会话信息并将其附加到Base

from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker

engine = create_engine("sqlite:///myapp.db")
db_session = scoped_session(sessionmaker(bind=engine))

Base.query = db_session.query_property()
Base.scoped_db_session = db_session

从Base创建我的模型并使用会话

class Person(Base):

    def store(self):
        if self.is_new():
            self.scoped_db_session.add(self)
        self.scoped_db_session.commit()

如果我创建了Person类型的足够对象并调用store(),那么该应用最终会冻结。

1 个答案:

答案 0 :(得分:0)

管理解决问题。事实证明我的实施是专门针对不要这样做的列表(参见http://docs.sqlalchemy.org/en/latest/orm/session_basics.html#session-frequently-asked-questions 例如,不要这样做)和我没有正确管理会话

为了解决我的问题,我将会话从模型中移到了一个单独的类中,所以不要像以下那样调用:

mymodel.store()

我现在有:

db.current_session.store(mymodel)

其中db是我的自定义DBContext的实例,如下所示:

from contextlib import contextmanager
from sqlalchemy.orm import scoped_session, sessionmaker

class DbContext(object):
    def __init__(self, engine, session=None):
        self._engine = engine
        self._session = session or scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=self._engine))
        self.query = self._session.query_property()
        self.current_session = None

    def start_session(self):
        self.current_session = self._session()

    def end_session(self):
        if self.current_session:
            self.current_session.commit()
            self.current_session.close()
        self.current_session = None

    @contextmanager
    def new_session(self):
        try:
            self.start_session()
            yield
        finally:
            self.end_session()

如果要存储一个或多个模型对象,请调用DBContext.start_session()以启动干净会话。当您最终想要提交时,请致电DBContext.end_session()