2015-11-30 13 views
5

Bazı blog yazılarını sorgulamak ve görüntülemek için SQLAlchemy kullanan bir Flask görünümü var. Uygulamı mod_wsgi kullanarak çalıştırıyorum. Bu görünüm, sayfaya ilk gittiğimde çalışır, ancak bir dahaki sefere 500 hata döndürür. Geri tepme, ProgrammingError: SQLite objects created in a thread can only be used in that same thread. hatasını gösterir Neden bu hatayı alıyorum ve nasıl düzeltebilirim?Flask'tan SQLAlchemy oturumu kullanıldığında "Bir iş parçacığıyla oluşturulan SQLite nesneleri yalnızca aynı iş parçacığında kullanılabilir"

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

views.py: Eğer parçacığı üzerinde bir oturum paylaşıyorsanız

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

cevap

6

SQLAlchemy (ve bu durumda SQLite da) çalışmıyor. Açıkça thread kullanmıyor olabilirsiniz, ancak mod_wsgi, ve global bir session nesnesini tanımlamışsınız. Her iş parçacığı için benzersiz bir oturum oluşturmayı yönetmek için scoped_session kullanın.

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

Tercihen, sizin için bu ve diğer şeyler kolları Flask-SQLAlchemy kullanın. SQLAlchemy dokümanları bunu kendiniz yapmak yerine bütünleştirme kitaplığını kullanmanızı önerir.

db = SQLAlchemy(app) 

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

Ayrıca ziyade mevcut kod yaptığı gibi her dosyaya yeniden tanımlama yerine, sadece bir kez, vb motor, oturumu tanımlayacağız ve başka bir yere ithal gerektiğini unutmayın.

+0

Çalışıyor. Spesifik olarak, scoped_session'ı sqlalchemy.orm'dan aldım ve daha sonra bu kılavuzda açıklandığı gibi bir "SessionParent" nesnesi oluşturdum http://docs.sqlalchemy.org/en/latest/orm/contextual.html –

2

this SO answer bir ipucu alarak ben SA dokümanlar arandı ve bunu yapabilirsiniz öğrendim:

engine = create_engine('sqlite:////var/www/homepage/blog.db?check_same_thread=False') 

scoped_session benim durumumda pek uygun değildi Flask-SQLAlchemy sadece bağlantı dizesi argüman alır başlangıcı:

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