0

这是我网站上的相关代码__init__.py

from site.models import initialise_sql

def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application """

    initialise_sql(settings['database.url'])

    return config.make_wsgi_app()

这是我的models/__init__.py

from storm.locals import *

from datetime import datetime

DBSession = None

class Tables:
    """ A simple namespace for all the table objects in our database """

    class Users(object):

        __storm_table__ = 'users'

        user_id      = Int(primary=True)
        username     = RawStr()
        password     = RawStr()
        date_created = DateTime(default=datetime.now())

def initialise_sql(db_uri):
    """ Initialise the database """

    global DBSession

    database  = create_database(db_uri)
    DBSession = Store(database)

这是我的用户模型:

def create_account(username, password):

    user = Tables.Users()
    user.username = username
    user.password = password

    DBSession.add(user)
    DBSession.flush()

根据我对 Storm 文档的阅读,这一切都是正确的。问题是,当create_account从我的视图可调用函数中调用该函数时,我会抛出以下异常:

ProgrammingError: SQLite objects created in a thread can only be used in that same thread.The object was created in thread id -1220417856 and this is thread id -1239418000

我什至不知道 Pyramid 正在线程化应用程序:/

我怎样才能解决这个问题?

4

2 回答 2

1

您使用的 Web 服务器是多线程的,而不是 Pyramid 本身。从处理请求的角度考虑您的应用程序会更安全。基本上,在任何给定时间点,每个线程都会有一个请求,因此每个活动请求都应该使用与数据库的不同连接。使用scoped_sessionfrom SQLAlchemy 可以轻松处理此问题,但您也可以使用类似于本 Pyramid 教程使用原始 SQLite 连接的方式来执行此操作。

这里的基本思想是它在订阅者中建立一个新的数据库连接NewRequest,因此可以保证跨请求共享连接不会出现任何线程问题。您还可以将此范例与连接池一起使用,我相信任何体面的 ORM 都会为您提供。

更新在仔细查看 Storm 之后,我没有看到对连接池的大量支持,但是有一个 ZStorm 包,它将 Storm 与Pyramid 使用的事务管理器集成在一起。这确实实现了一些池化机制,可以让你的生活更轻松。

于 2011-07-16T20:57:37.723 回答
0
global DBSession

是你的问题。Storm 手册对此非常明确

您需要使用线程本地存储。threading.local 是答案:

import threading
tlocal = threading.local()

def initialise_sql(db_uri):
    global tlocal
    db = create_database(db_uri)
    tlocal.dbsession = Store(db)

#etc
于 2011-07-21T13:44:38.720 回答