Пытаюсь заставить Storm ORM работать с Пирамидой, но у меня проблемы с потоками - PullRequest
0 голосов
/ 16 июля 2011

Вот соответствующий код с моих сайтов __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 создает потоки приложения: /

Как я могу это исправить?

Ответы [ 2 ]

1 голос
/ 17 июля 2011

Веб-сервер, который вы используете, является многопоточным, а не самой Пирамидой. Более безопасно думать о вашем приложении с точки зрения обработки запросов. Как правило, в каждый конкретный момент времени у вас будет один запрос на поток, поэтому каждый активный запрос должен использовать другое соединение с базой данных. Это выполняется тривиально, используя scoped_session из SQLAlchemy, но вы также можете сделать это способом, аналогичным , который этот учебник по пирамиде делает с необработанными соединениями SQLite.

Основная идея здесь заключается в том, что он устанавливает новое соединение с базой данных у подписчика NewRequest, поэтому вы гарантированно не столкнетесь с проблемами потоков при совместном использовании соединений между запросами. Вы также можете использовать эту парадигму с пулом соединений, который, я уверен, любой приличный ORM предоставляет вам.

Обновление После более внимательного изучения Storm я не вижу тонны поддержки пула соединений, но есть пакет ZStorm, который интегрирует Storm с менеджером транзакций что пирамида использует. Это реализует некоторые механизмы объединения, которые облегчили бы вашу жизнь.

0 голосов
/ 21 июля 2011
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
...