Pandas 和 SQLAlchemy:使用来自 engine.begin() 的连接时,带有 SQLAlchemy 2.0 fututre=True 的 df.to_sql() 会引发错误

Posted

技术标签:

【中文标题】Pandas 和 SQLAlchemy:使用来自 engine.begin() 的连接时,带有 SQLAlchemy 2.0 fututre=True 的 df.to_sql() 会引发错误【英文标题】:Pandas and SQLAlchemy: df.to_sql() with SQLAlchemy 2.0 fututre=True throws an error when using a connection from engine.begin() 【发布时间】:2022-01-01 03:03:45 【问题描述】:

我试图在 MS SQL Server 中从 pandas DataFrame 中插入一个表。

据我了解,这是一个两步过程:

在临时表中执行 pandas df.to_sql() 执行神奇的 sql 将临时表合并到现有的最终表中

这可行,但前提是我在 create_engine 调用中设置了 future=False。

   self.engine = create_engine(self.url, echo=True, future=False)
  with self.engine.begin() as conn:
            df.to_sql("#update_table", conn, if_exists="append", index=False)
            # merge...
            sql = f"""\
            -- magic sql
            """
            result = conn.execute(text(sql)).fetchone()

当使用 future=True 我得到这个错误:

Traceback (most recent call last):
  File "/usr/local/Caskroom/miniconda/base/envs/dc_uk/lib/python3.9/site-packages/pandas/io/sql.py", line 1340, in insert_records
    table.insert(chunksize=chunksize, method=method)
  File "/usr/local/Caskroom/miniconda/base/envs/dc_uk/lib/python3.9/site-packages/pandas/io/sql.py", line 959, in insert
    with self.pd_sql.run_transaction() as conn:
  File "/usr/local/Caskroom/miniconda/base/envs/dc_uk/lib/python3.9/contextlib.py", line 119, in __enter__
    return next(self.gen)
  File "/usr/local/Caskroom/miniconda/base/envs/dc_uk/lib/python3.9/site-packages/pandas/io/sql.py", line 1416, in run_transaction
    with self.connectable.begin() as tx:
  File "/usr/local/Caskroom/miniconda/base/envs/dc_uk/lib/python3.9/site-packages/sqlalchemy/future/engine.py", line 144, in begin
    return super(Connection, self).begin()
  File "/usr/local/Caskroom/miniconda/base/envs/dc_uk/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 766, in begin
    raise exc.InvalidRequestError(
sqlalchemy.exc.InvalidRequestError: This connection has already initialized a SQLAlchemy Transaction() object via begin() or autobegin; can't call begin() here unless rollback() or commit() is called first.

似乎 pandas 中的某些东西(还)无法处理 SA2 中的变化。 :(

今年早些时候有一些关于 SQLAlchemy 2.0 的问题,但都已解决。

我的问题: 我做错什么了吗?或者这仍然是一个悬而未决的问题...?

PS: 这是在 mac、python 3.9.7、pandas 1.3.4 和 SQLAlchemy 1.4.27 上。

【问题讨论】:

【参考方案1】:

根据文档,“未来”会导致事务自动启动,因此您无需调用 .begin()

例如

with engine.connect() as conn:
    conn.execute(...)
    conn.execute(...)
    conn.commit()

    conn.execute(...)
    conn.execute(...)
    conn.commit()

method sqlalchemy.future.Connection.begin()

【讨论】:

给出一个新错误:File "/Users/ar/src/fuelminr/dc_uk_gold/src/DataFactory/scores.py", line 301, in scores_upsert with self.engine as conn: AttributeError: __enter__... :/

以上是关于Pandas 和 SQLAlchemy:使用来自 engine.begin() 的连接时,带有 SQLAlchemy 2.0 fututre=True 的 df.to_sql() 会引发错误的主要内容,如果未能解决你的问题,请参考以下文章

截断表不适用于 SQL Server sqlalchemy 引擎和 pandas

如何在 SQLAlchemy 的`create_engine` 中使用`charset` 和`encoding`(创建pandas 数据框)?

如何使用 pandas sqlalchemy 和 psycopg2 处理 NaT

想要使用 pandas 和 sqlalchemy 从查询是变量(不和谐用户名)的数据库中选择所有内容

无法在 ETL 过程中使用 Pandas 和 SQLAlchemy 将列名从 CSV 更改为 SQL Server DB

使用 sqlalchemy 从 PostgreSQL 查询返回 Pandas 数据框