当使用连接池时,SQLAlchemy键错误。
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了当使用连接池时,SQLAlchemy键错误。相关的知识,希望对你有一定的参考价值。
我为Person创建了一个存储库类,里面有下面的方法。
def find_by_order_id(self, order_id: str) -> [Person]:
results = []
client_table = Table(TBL_CLIENT, self._metadata, autoload=True,
autoload_with=self._connection)
order_table = Table(TBL_ORDER, self._metadata, autoload=True,
autoload_with=self._connection)
query = select([client_table.c.first_name, client_table.c.last_name, client_table.c.date_of_birth])
.select_from(
order_table.join(client_table, client_table.c.order_id = order_table.c.order_id)
).where(order_table.c.order_id == order_id).distinct()
for row in self._connection.execute(query).fetchall():
results.append(dict(row))
return results
由于一些我无法解释的奇怪原因,当我调试代码时,我有时会从SQLAlchemy那里得到一个实际存在的keyError。
File "/home/tghasemi/miniconda3/envs/myproj/lib/python3.6/site-packages/sqlalchemy/util/_collections.py", line 210, in __getattr__
return self._data[key]
KeyError: 'order_id'
我注意到这种情况只发生在多线程时从连接池中提取连接时(每个线程只使用一个连接--我知道连接不是线程安全的)。
if use_pooling:
self._engine = create_engine(connection_string, pool_size=db_pool_size,
pool_pre_ping=db_pool_pre_ping, echo=db_echo)
else:
self._engine = create_engine(connection_string, echo=db_echo)
考虑到当我在异常发生的地方设置一个断点时,键是存在的(甚至在异常发生时也检查了它),我怀疑在构建查询时,表的加载还没有完成。
有人知道为什么会发生这样的事情吗? 我放弃了!
答案
好吧,我想我设法解决了这个问题。
我在我的问题中没有提到的东西(事实上,我没有想到它的可能性)是引擎和MetaData对象都来自于我为数据库创建的Singleton类。
class Database(metaclass=SingletonMetaClass):
def __init__(self, config: Config, use_pooling: bool = True, logger: Logger = None):
# Initializing the stuff here ...
@property
def metadata(self): # used to return self._metadata here
return MetaData(self._engine, reflect=False, schema=self._db_schema)
@property
def engine(self):
return self._engine
尽管SQLAlchemy的官方文档说MetaData对象对读操作是线程安全的,但由于某些原因,在我的情况下(这是一个读操作),它导致了这个问题。不知道为什么,在我的线程之间不共享这个对象后,问题就消失了(不是100%确定是否真的消失了,但现在不再发生了)。
以上是关于当使用连接池时,SQLAlchemy键错误。的主要内容,如果未能解决你的问题,请参考以下文章
尝试连接数据库和 Web 容器时 SQLAlchemy 连接被拒绝
Flask-SqlAlchemy - 与列''关联的外键无法找到表