Reputation: 7867
Here's the relevant code from my websites __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()
Here's my 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)
And here's my users model:
def create_account(username, password):
user = Tables.Users()
user.username = username
user.password = password
DBSession.add(user)
DBSession.flush()
From what I've read of the Storm documentation, this is all correct. The problem is, when the create_account
function is called from my view callable, I get the following exception thrown:
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
I wasn't even aware Pyramid was threading the application :/
How can I fix this?
Upvotes: 0
Views: 729
Reputation: 23331
The web server you're using is multithreaded, not Pyramid itself. It's safer to think about your application in terms of handling requests. Basically you'll have one request per thread at any given point in time, so each active request should be using a different connection to the database. This is handled trivially using the scoped_session
from SQLAlchemy, but you can also do this in a manner similar to the way this Pyramid tutorial does it with raw SQLite connections.
The basic idea here is that it establishes a new connection the database in a NewRequest
subscriber, so you're guaranteed there won't be any threading issues from sharing connections across requests. You can also use this paradigm with a connection pool which I'm sure any decent ORM is supplying you.
Update After looking at Storm more carefully, I don't see a ton of support for connection pooling, but there is the ZStorm package which will integrate Storm with the transaction manager that Pyramid uses. This does implement some pooling mechanisms that would make your life easier.
Upvotes: 1
Reputation: 1879
global DBSession
is your problem. The Storm manual is very explicit about this.
You need to use a thread-local storage. threading.local is the answer:
import threading
tlocal = threading.local()
def initialise_sql(db_uri):
global tlocal
db = create_database(db_uri)
tlocal.dbsession = Store(db)
#etc
Upvotes: 0