【问题标题】:SQLAlchemy v1.4 ObjectNotExecutableError when executing any SQL query using AsyncEngine使用 AsyncEngine 执行任何 SQL 查询时出现 SQLAlchemy v1.4 ObjectNotExecutableError
【发布时间】:2021-11-28 02:15:03
【问题描述】:

我正在使用异步引擎。当我尝试执行任何操作时:

async with self.async_engine.connect() as con:
    query = "SELECT id, name FROM item LIMIT 50;"
    result = await con.execute(f"{query}")

我明白了:

Exception has occurred: ObjectNotExecutableError
Not an executable object: 'SELECT id, name FROM item LIMIT 50;'

这个问题之前是用户@stilmaniac 提出的,但现在是deleted from SO

我在 Google 搜索缓存中找到了它,here is copy

我有同样的问题,所以我重新问一下,但原始版本如下:


我正在尝试从元数据创建表,如下所示:

Base = declarative_base()

properties = Table(
    'properties', Base.metadata,
    # ...
    Column('geolocation', Geography(geometry_type='POINT', srid=4326)),
    # ... 
)

engine = create_async_engine("postgresql+asyncpg://user:password@postgres/")
async with engine.begin() as conn:
    await conn.run_sync(Base.metadata.create_all)

给我以下错误:

sqlalchemy.exc.ObjectNotExecutableError: Not an executable object: 'CREATE INDEX "idx_properties_geolocation" ON "properties" USING GIST ("geolocation")'

考虑到这个doc

版本:

  • 操作系统:macOS 11.4 ARM
  • SQLAlchemy:1.4.22
  • Python:3.6

【问题讨论】:

  • 你试过不使用 f 字符串吗?
  • @ReedJones f"{}" 给出与str() 相同的结果,这不是原因。

标签: python python-3.x sqlalchemy python-asyncio asyncpg


【解决方案1】:

正如异常消息所暗示的,str 'SELECT id, name FROM item LIMIT 50;' 不是可执行对象。要使其可执行,请使用sqlalchemy.text 包装它。

from sqlalchemy import text

async with self.async_engine.connect() as con:
    query = "SELECT id, name FROM item LIMIT 50;"
    result = await con.execute(text(query))

async.connection.execute 要求它的语句参数

[...] 始终是在 ClauseElement 和 可执行的层次结构,包括:

  • 选择

  • 插入、更新、删除

  • TextClause 和 TextualSelect

  • DDL 和继承自 DDLElement 的对象

同步 connection.execute 方法允许使用原始字符串,但在 SQLAlchemy 2.0 中已弃用并标记为删除。

【讨论】:

  • 它不再给出这个异常,但它不能正常工作(结果为空)。同样在标准同步 SQLAlchemy 中,我不需要使用 text()。这似乎是 SQLAlchemy 的一个错误,因为如果我首先创建 AsyncSession 并使用它,一切正常。
  • 您是否正在获取结果,例如print(result.fetchall())?
  • 是的,当我使用 async_engine 时这是空的。使用 sync_engine 它不是空的。
  • 那么其他地方出了问题,因为上面的代码有效,并且与文档中的示例代码基本相同。如果你将echo=True 传递给create_engine,你看到你的SQL 正在执行吗?
  • 我无法再重现此问题。可能我在之前的调试过程中误读了一些东西。使用 text() 是必要的,这是问题错误的原因。当我使用它时,我得到了正确的结果。 echo=True 工作正常,我看到了 SQL。感谢您的帮助。
猜你喜欢
  • 2015-07-22
  • 2011-06-26
  • 2016-11-11
  • 2017-05-13
  • 1970-01-01
  • 2020-12-01
  • 1970-01-01
  • 2012-02-24
  • 2018-01-16
相关资源
最近更新 更多