在多线程环境中运行的sqlalchemy sqlite

时间:2018-10-06 01:17:34

标签: python sqlite sqlalchemy

在多线程环境中使用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是否适合这种环境。

0 个答案:

没有答案
相关问题