在多线程环境中使用sqlite配置sqlalchemy ORM后遇到问题。这是我想要达到的目标。我正在尝试使用Paho mqtt python库订阅mqtt主题。 mqttsubscribe类在单独的线程中运行。 MqttSubscribe类在初始化该类时回调我注册的函数。每当有消息即时消息试图使用定义的models.py写入数据库时。这是models.py的示例代码。
import os
import datetime
from sqlalchemy.orm import sessionmaker, relationship
from sqlalchemy.pool import StaticPool, NullPool
from sqlalchemy.engine import Engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import create_engine, event, Column, Integer, String, DateTime, Boolean, ForeignKey, and_, desc
Base = declarative_base()
Session = sessionmaker()
session = ''
# Sqlite doesnt support foreign key by default
# Below code is logic is taken from
# https://stackoverflow.com/questions/31794195/
# how-to-correctly-add-foreign-key-constraints-to-sqlite-db-using-sqlalchemy
@event.listens_for(Engine, "connect")
def set_sqlite_pragma(connection, connection_record):
cursor = connection.cursor()
cursor.execute("PRAGMA foreign_keys=ON")
cursor.close()
def init_db_connection(engine, echo=True):
global session
engine = create_engine(engine, echo=echo)
Session.configure(bind=engine, connect_args={'check_same_thread':False},
poolclass=NullPool)
session = Session()
Base.metadata.create_all(engine)
return session
class Person(Base):
__tablename__ = 'Person'
id = Column(Integer, primary_key=True)
first_name = Column(String(50))
last_name = Column(String(50))
created_on = Column(DateTime, nullable=False, default=datetime.datetime.utcnow())
updated_on = Column(DateTime, nullable=False, default=datetime.datetime.utcnow(),\
onupdate=datetime.datetime.utcnow())
def __init__(self, first_name, last_name):
self.last_name = last_name
self.first_name = first_name
@classmethod
def create(cls, first_name, last_name):
result = cls(first_name, last_name)
session.add(result)
session.commit()
return result
def __repr__(self):
return "<Person (name=%s last_name=%s)>" % (self.first_name, self.last_name)
我正在尝试通过导入model.py和init_db_connection在另一个库中使用此方法初始化db_connnection
init_db_connection('sqlite:////tmp/foo.db', echo=False)
current_time = datetime.datetime.utcnow()
time.sleep(1)
print('Current_time: {}'.format(current_time))
person = Person.create('Andy','Boss')
print('Person name: {}'.format(person.first_name))
回调函数能够从不同的线程写入数据库。我在读取数据库时面临问题。我遇到此错误
self = <sqlalchemy.orm.session.SessionTransaction object at 0x756550b0>, prepared_ok = False, rollback_ok = False, deactive_ok = False
closed_msg = 'This transaction is closed'
def _assert_active(self, prepared_ok=False,
rollback_ok=False,
deactive_ok=False,
closed_msg="This transaction is closed"):
if self._state is COMMITTED:
raise sa_exc.InvalidRequestError(
"This session is in 'committed' state; no further "
"SQL can be emitted within this transaction."
)
elif self._state is PREPARED:
if not prepared_ok:
raise sa_exc.InvalidRequestError(
> "This session is in 'prepared' state; no further "
"SQL can be emitted within this transaction."
E sqlalchemy.exc.InvalidRequestError: This session is in 'prepared' state; no further SQL can be emitted within this transaction.
sanity/lib/python3.5/site-packages/sqlalchemy/orm/session.py:264: InvalidRequestError
我应该使用scoped_session而不是session来解决此问题吗?我不认为sqlite是否适合这种环境。