Использование сеанса SQLAlchemy из колбы вызывает " объекты SQLite, созданные в потоке, могут использоваться только в том же потоке"
у меня есть представление колбы, которое использует SQLAlchemy для запроса и отображения некоторых сообщений в блоге. Я запускаю свое приложение с помощью mod_wsgi. Это представление работает при первом переходе на страницу, но в следующий раз возвращает ошибку 500. Трассировка показывает ошибку ProgrammingError: SQLite objects created in a thread can only be used in that same thread.
почему я получаю эту ошибку и как это исправить?
views.py
engine = create_engine('sqlite:////var/www/homepage/blog.db')
Base.metadata.bind = engine
DBSession = sessionmaker(bind = engine)
session = DBSession()
@app.route('/blog')
@app.route('/blog.html')
def blog():
entrys = session.query(Entry).order_by(desc(Entry.timestamp)).all()
return render_template('blog.html', blog_entrys = entrys)
models.py
:
class Entry(Base):
__tablename__ = 'entry'
id = Column(Integer, primary_key = True)
title = Column(String(100), nullable = False)
body = Column(String, nullable = False)
timestamp = Column(DateTime, nullable = False)
featured = Column(Boolean, nullable = False)
comments = relationship('Comment')
def is_featured(self):
return self.featured
class Comment(Base):
__tablename__ = 'comment'
id = Column(Integer, primary_key = True)
entry_id = Column(Integer, ForeignKey('entry.id'))
text = Column(String(500), nullable = False)
name = Column(String(80))
engine = create_engine('sqlite:////var/www/homepage/blog.db')
Base.metadata.create_all(engine)
Exception on /blog.html [GET]
Traceback (most recent call last):
File "/usr/lib/python2.6/dist-packages/flask/app.py", line 861, in wsgi_app
rv = self.dispatch_request()
File "/usr/lib/python2.6/dist-packages/flask/app.py", line 696, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/var/www/homepage/webserver.py", line 38, in blog
entrys = session.query(Entry).order_by(desc(Entry.timestamp)).all()
File "/usr/lib/python2.6/dist-packages/sqlalchemy/orm/query.py", line 1453, in all
return list(self)
File "/usr/lib/python2.6/dist-packages/sqlalchemy/orm/query.py", line 1565, in __iter__
return self._execute_and_instances(context)
File "/usr/lib/python2.6/dist-packages/sqlalchemy/orm/query.py", line 1570, in _execute_and_instances
mapper=self._mapper_zero_or_none())
File "/usr/lib/python2.6/dist-packages/sqlalchemy/orm/session.py", line 735, in execute
clause, params or {})
File "/usr/lib/python2.6/dist-packages/sqlalchemy/engine/base.py", line 1157, in execute
params)
File "/usr/lib/python2.6/dist-packages/sqlalchemy/engine/base.py", line 1235, in _execute_clauseelement
parameters=params
File "/usr/lib/python2.6/dist-packages/sqlalchemy/engine/base.py", line 1348, in __create_execution_context
None, None)
File "/usr/lib/python2.6/dist-packages/sqlalchemy/engine/base.py", line 1343, in __create_execution_context
connection=self, **kwargs)
File "/usr/lib/python2.6/dist-packages/sqlalchemy/engine/default.py", line 381, in __init__
self.cursor = self.create_cursor()
File "/usr/lib/python2.6/dist-packages/sqlalchemy/engine/default.py", line 523, in create_cursor
return self._connection.connection.cursor()
File "/usr/lib/python2.6/dist-packages/sqlalchemy/pool.py", line 383, in cursor
c = self.connection.cursor(*args, **kwargs)
ProgrammingError: (ProgrammingError) SQLite objects created in a thread can only be used in that same thread.The object was created in thread id 140244498364160 and this is thread id 140244523542272 None [{}]
2 ответов
SQLAlchemy (и в этом случае SQLite также) не работает, если вы разделяете сеанс между потоками. Возможно, вы не используете потоки явно, но mod_wsgi
есть, и вы определили глобальный session
"объект". Либо используйте scoped_session
для обработки создания уникального сеанса для каждого потока.
session = scoped_session(sessionmaker(bind=engine))
@app.teardown_request
def remove_session(ex=None):
session.remove()
@app.route('/')
def example():
item = session.query(MyModel).filter(...).all()
...
желательно, использовать Колба-SQLAlchemy который обрабатывает это и другие вещи для вас. В документах SQLAlchemy рекомендуется использовать библиотеку интеграции, а не сделай это сам.
db = SQLAlchemy(app)
@app.route('/')
def example():
item = db.session.query(MyModel).filter(...).all()
...
также обратите внимание,что вы должны определять только движок, сеанс и т. д. один раз и импортировать его в другом месте, а не переопределять его в каждом файле, как ваш текущий код.
принимая намек от это так ответ Я искал SA docs и узнал, что вы можете это сделать:
engine = create_engine('sqlite:////var/www/homepage/blog.db?check_same_thread=False')
scoped_session
не очень подходит в моем случае, так как Flask-SQLAlchemy принимает только аргумент строки подключения:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
class Config(object):
SQLALCHEMY_DATABASE_URI = 'sqlite:///app.db?check_same_thread=False'
db = SQLAlchemy()
def create_app():
app.config.from_object(Config)
app = Flask(__name__)
db.init_app(app)
...