Python 是否有任何sqlalchemy列表插值语法可以在sqlite(用于测试)和mysql(用于prod)中使用?

Python 是否有任何sqlalchemy列表插值语法可以在sqlite(用于测试)和mysql(用于prod)中使用?,python,mysql,sqlite,sqlalchemy,Python,Mysql,Sqlite,Sqlalchemy,这是我需要处理的最微小的代码示例我们在prod中使用mysql,我们喜欢原始sql查询来处理复杂的查询,因为数据分析师可以读取/修改/审计它们,我们使用sqlite进行单元测试 from typing import List, Any def test_sqlite_params_demo(self, session): session.add(build_foo()) session.commit() query = "select * f

这是我需要处理的最微小的代码示例我们在prod中使用mysql,我们喜欢原始sql查询来处理复杂的查询,因为数据分析师可以读取/修改/审计它们,我们使用sqlite进行单元测试

    from typing import List, Any

    def test_sqlite_params_demo(self, session):
      session.add(build_foo())
      session.commit()
      query = "select * from foo where id not in :id_list"
      result = session.execute(query, {"id_list": [9, 99, 999]})
      result_dict: List[Any] = [dict(r) for r in result]
      assert len(result_dict) is 1
以下是上述操作导致的错误:

        def do_execute(self, cursor, statement, parameters, context=None):
>       cursor.execute(statement, parameters)
E       sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) near "?": syntax error
E       [SQL: select * from patient where id not in ?]
E       [parameters: ([9, 99, 999],)]
E       (Background on this error at: http://sqlalche.me/e/e3q8)
如果我使用一个元组result=session.executequery,{id_list:9,99,999},则错误为:

>       cursor.execute(statement, parameters)
E       sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) near "?": syntax error
E       [SQL: select * from foo where id not in ?]
E       [parameters: ((9, 99, 999),)]
E       (Background on this error at: http://sqlalche.me/e/e3q8)
注意:此问题仅在插入列表而不仅仅是单个值时发生

我在requirements.txt文件中使用SQLAlchemy==1.3.11

现在我面临着一个令人不快的选择,要么在添加测试之前将复杂的代码重写为不太理想的格式,要么添加跳过/模拟我最想测试的代码部分的测试。什么是更好的选择


这个问题以前一定有人问过,但我一直找不到。如果您知道它在哪里,请给我指一下:

如果您将查询转换为sqlalchemy.text对象,应该可以

从sqlalchemy导入文本 结果=session.executetextquery,{id_list:[9,99999]}
我已经创造了一个适合我的答案

def is_test():
  """
  Tests which want to run code that executes raw sql can override this to be True
  Example:
  @patch('my_app.helpers.raw_sql_runner.is_test', side_effect=lambda: True)
  def test_run_raw_sql_string(self, is_test_mock, session):
  """
  return False

def run_raw_sql(session, sql, params):
  if is_test():
    for key, val in params.items():
        if isinstance(val, (list, tuple)):
            interpolated_sql = sql.replace(f':{key}', f"({','.join(map(str, val))})")
        elif isinstance(val, str):
            interpolated_sql = sql.replace(f':{key}', f"'{str(val)}'")
        else:
            interpolated_sql = sql.replace(f':{key}', str(val))
    return session.execute(interpolated_sql, params)
  else:
    return session.execute(sql, params)
我还需要创建一些mysql拥有的、sqlite没有的方法

# conftest.py
def fake_sqlite_concat(a, b):
  return f'{a}{b}'

def create_sqlite_functions(con):
  con.create_function("concat", 2, fake_sqlite_concat)
  # more functions go here as needed

con = engine.connect().connection
create_sqlite_functions(con)

此解决方案不会更改我看到的错误消息:您使用的是什么版本的sqlalchemy?我有SQLAlchemy==1.3.11