【发布时间】:2017-03-01 16:35:34
【问题描述】:
试图了解以下问题的原因让我非常头疼。我们正在使用以下库的组合:
- pyTelegramBotAPI 以多线程方式处理请求
- SQLAlchemy
- sqlite
SQLAlchemy 最初使用NullPool,现在配置为使用QueuePool。我还使用以下成语为每个线程启动一个新的数据库会话(根据我的理解)
Session = sessionmaker(bind=create_engine(classes.db_url, poolclass=QueuePool))
@contextmanager
def session_scope():
session = Session()
try:
yield session
session.commit()
except:
session.rollback()
raise
finally:
session.close()
@bot.message_handler(content_types=['document'])
def method_handler:
with session_scope() as session:
do_database_stuff_here(session)
尽管如此,我仍然遇到这个烦人的异常:(sqlite3.ProgrammingError) SQLite objects created in a thread can only be used in that same thread
有什么想法吗? ;) 特别是,我不明白另一个胎面怎么可能在数据库操作之间的某个地方......这可能是讨厌的异常的原因
更新 1:如果我将 poolclass 更改为 SingletonThreadPool,那么似乎不会再出现错误。但是,SQLAlchemy 的文档表明它不是生产盛行。
【问题讨论】:
-
当您说
NullThreadPool时,您是指NullPool吗?为什么需要使用QueuePool? -
来自 SQLAlchemy 文档:“当指定基于文件的数据库时,方言将使用 NullPool 作为连接源。此池将关闭并丢弃立即返回池的连接。SQLite 文件-基于连接的开销极低,因此不需要池化。该方案还可以防止连接在不同的线程中再次使用,并且最适合 SQLite 的粗粒度文件锁定。"
-
正如 xli 所说,您为什么要尝试使用
QueuePool? docs 很清楚,你可以使用NullPool、SingletonThreadPool或StaticPool。 -
@xli,是的,我的意思是
NullPool;) 感谢您的更正。使用QueuePool的想法是让多个(读取)线程同时可用。为什么会出错? @xli,@Peter Brittain,SqlAlchemy的默认实现使用NullPool,但我在使用它时遇到了异常(如上所述)。我不知道我为什么要得到它们,因为通过使用@contextmanager 应该保证我每个线程打开一个连接... -
我收到了您在多个线程使用
QueuePool执行数据库操作时显示的错误,但它在NullPool中消失了。您是否可以在with块中有多个线程,或者您能描述一下您在那里做什么?
标签: python multithreading sqlite sqlalchemy py-telegram-bot-api