使用Flask的SQLAlchemy会话引发了“线程中创建的SQLite对象只能在同一个线程中使用” [英] Using SQLAlchemy session from Flask raises "SQLite objects created in a thread can only be used in that same thread"

查看:328
本文介绍了使用Flask的SQLAlchemy会话引发了“线程中创建的SQLite对象只能在同一个线程中使用”的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Flask视图,它使用SQLAlchemy来查询和显示一些博客文章。我使用mod_wsgi运行我的应用程序。这个视图是我第一次进入页面,但下一次返回500错误。回溯显示错误 ProgrammingError:在线程中创建的SQLite对象只能在同一个线程中使用。为什么我得到这个错误,我该如何解决? p>

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

 类Entry(Base):
__tablename__ ='entry'
$ b 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')
$ b $ def is_featured(self):
return self.featured


class Comment(Base):
__tablename__ ='comment'
$ b $ id = Column(Integer,primary_key = True )
entry_id = Column(Integer,ForeignKey('entry.id'))
$ b $ text = Column(String(500),nullable = False)
name = Column (80))


engine = create_engine('sqlite:////var/www/homepage/blog.db')
Base.metadata.create_all(引擎)





  .html [GET] 
Traceback(最近一次调用的最后一个):
在wsgi_app $ b中的文件/usr/lib/python2.6/dist-packages/flask/app.py,第861行$ b rv = self.dispatch_request()
文件/usr/lib/python2.6/dist-packages/flask/app.py,第696行,在dispatch_request
返回self.view_functions [rule .endpoint]( ** req.view_args)
文件/var/www/homepage/webserver.py,第38行,在博客
entrys = session.query(Entry).order_by(desc(Entry.timestamp) ).all()
文件/usr/lib/python2.6/dist-packages/sqlalchemy/orm/query.py,行1453,在所有
返回列表(self)
文件/usr/lib/python2.6/dist-packages/sqlalchemy/orm/query.py,第1565行,在__iter__
中返回self._execute_and_instances(context)
文件/ usr / lib / python2.6 / dist-packages / sqlalchemy / orm / query.py,第1570行,在_execute_and_instances
mapper = self._mapper_zero_or_none())
文件/usr/lib/python2.6 /dist-packages/sqlalchemy/orm/session.py,第735行,执行
子句,params或{})
文件/usr/lib/python2.6/dist-packages/sqlalchemy /engine/base.py,第1157行,执行
params)
文件/usr/lib/python2.6/dist-packages/sqlalchemy/engine/base.py,第1235行,在_execute_clauseelement中
parameters = params
文件/usr/lib/python2.6/dist-packages/s qlalchemy / engine / base.py,第1348行,在__create_execution_context
无,无)
文件/usr/lib/python2.6/dist-packages/sqlalchemy/engine/base.py,第1343行,在__create_execution_context
connection = self,** kwargs)
文件/usr/lib/python2.6/dist-packages/sqlalchemy/engine/default.py,第381行,在__init__
self.cursor = self.create_cursor()
文件/usr/lib/python2.6/dist-packages/sqlalchemy/engine/default.py,第523行,在create_cursor
返回self._connection.connection.cursor()
在游标
c = self.connection中的文件/usr/lib/python2.6/dist-packages/sqlalchemy/pool.py,行383。游标(* args,** kwargs)
ProgrammingError:(ProgrammingError)在一个线程中创建的SQLite对象只能在同一个线程中使用。该对象是在线程ID 140244498364160中创建的,这是线程ID 140244523542272 None [ }]


解决方案

SQLAlchemy所以)如果您跨线程共享会话不起作用。您可能不会显式地使用线程,但是 mod_wsgi 是,并且已经定义了一个全局会话对象。请使用 scoped_session 为每个线程处理创建一个独特的会话。



$ p $ 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()
...

最好使用 Flask-SQLAlchemy 来处理这个和其他的东西给你。 SQLAlchemy文档建议您使用集成库,而不是自己做。

  db = SQLAlchemy(app)

@ app.route('/')
def example():
item = db.session.query(MyModel).filter(...)。all()
...

另外请注意,您应该只定义一次引擎,会话等并导入它在其他地方,而不是像你现有的代码重新定义在每个文件中。


I have a Flask view which uses SQLAlchemy to query and display some blog posts. I am running my app using mod_wsgi. This view works the first time I go to the page, but returns a 500 error next time. The traceback shows the error ProgrammingError: SQLite objects created in a thread can only be used in that same thread. Why am I getting this error and how do I fix it?

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 [{}]

解决方案

SQLAlchemy (and in this case SQLite also) doesn't work if you share a session across threads. You may not be using threads explicitly, but mod_wsgi is, and you've defined a global session object. Either use scoped_session to handle creating a unique session for each thread.

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()
    ...

Preferably, use Flask-SQLAlchemy which handles this and other things for you. The SQLAlchemy docs recommend you use the integration library rather than doing this yourself.

db = SQLAlchemy(app)

@app.route('/')
def example():
    item = db.session.query(MyModel).filter(...).all()
    ...

Also note that you should only be defining the engine, session, etc. once and importing it elsewhere, rather than redefining it in each file like your current code does.

这篇关于使用Flask的SQLAlchemy会话引发了“线程中创建的SQLite对象只能在同一个线程中使用”的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆