【问题标题】:ProgrammingError Thread error in SQLAlchemyProgrammingError SQLAlchemy中的线程错误
【发布时间】:2013-02-14 22:33:53
【问题描述】:

我在一个 sqlite 数据库中有两个简单的表。

from sqlalchemy import MetaData, Table, Column, Integer, ForeignKey, \
    create_engine, String
from sqlalchemy.orm import mapper, relationship, sessionmaker, scoped_session
from sqlalchemy.ext.declarative import declarative_base

engine = create_engine('sqlite:///dir_graph.sqlite', echo=True)

session_factory = sessionmaker(bind=engine)
Session = scoped_session(session_factory)
session = Session()

Base = declarative_base()

class NodeType(Base):
    __tablename__ = 'nodetype'
    id = Column(Integer, primary_key=True)
    name = Column(String(20), unique=True)
    nodes = relationship('Node', backref='nodetype')

def __init__(self, name):
    self.name = name

def __repr__(self):
    return "Nodetype: %s" % self.name


class Node(Base):
    __tablename__ = 'node'

    id = Column(Integer, primary_key=True)
    name = Column(String(20), unique=True)
    type_id = Column(Integer,
                 ForeignKey('nodetype.id'))


    def __init__(self, _name, _type_id):
        self.name = _name
        self.type_id = _type_id

Base.metadata.create_all(engine) 

运行后我与解释器交互。例如n1= Node('Node1',1) 了解 sqlalchemy。在我做了一个 session.commit() 并尝试另一个语句之后,例如n2 = Node('n2',1) 我得到这个错误: sqlalchemy.exc.ProgrammingError: (ProgrammingError) 在一个线程中创建的 SQLite 对象只能在同一个线程中使用。该对象是在线程 id 3932 中创建的,这是线程 id 5740 无 无。

提交后如何继续会话? tnx

【问题讨论】:

  • 该错误是一个 SQLite 驱动程序错误,正如它所说的那样,你不能在两个不同的线程中使用连接 - 这里还有更多的故事,你是如何运行会议在这里?有什么线程正在进行吗?
  • 线程没有故意的。我在 Spyder 中运行此代码。运行设置是在运行后与解释器进行交互。这就是我所做的。看起来 commit() 关闭了连接,然后我重新初始化了。我没有在 SQLalchemy 文档中找到 excat 提示。
  • 尝试在默认的 Python 解释器中运行或作为单个脚本运行。从未听说过“Spyder”,但它可能会用线程做一些奇怪的事情。
  • 嗨@zzzeek,我认为这种情况发生了很多。特别是对于密集使用 TwistedThread 延迟机制的应用程序。我整天都在试图解决这个案子。有什么建议我可以在扭曲的延迟线程中安全地使用 sqlalchemy 吗?
  • 以前从未使用过 twisted,但您需要确保特定的 SQLAlchemy 会话保持与单个操作系列挂钩,并且不会与执行不同操作的其他系列操作共享。 “线程本地”会话可能适合也可能不适合twisted 的线程池。当人们尝试使用带 twisted 的普通库时,我毫不怀疑这个问题经常发生,因为将 twisted 与线程代码混合使用必然需要对并发有相当程度的熟悉。

标签: sqlite sqlalchemy


【解决方案1】:

默认情况下,SQLite 禁止在多个线程中使用单个连接。 只需将connect_args={'check_same_thread': False} 参数添加到您的engine 变量中,例如

engine = create_engine('sqlite:///dir_graph.sqlite', connect_args={'check_same_thread': False}, echo=True)

根据sqlite3.connect

默认情况下,check_same_threadTrue,只有创建线程可以 使用连接。如果设置False,返回的连接可能是 跨多个线程共享。 当使用多个线程时 用户应序列化相同的连接写入操作以 避免数据损坏。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-02-27
    • 2016-02-12
    • 1970-01-01
    • 2020-07-16
    • 2018-10-05
    • 1970-01-01
    • 1970-01-01
    • 2019-11-10
    相关资源
    最近更新 更多