【问题标题】:sqlite + pandas: database table is lockedsqlite + pandas:数据库表被锁定
【发布时间】:2021-02-22 01:03:51
【问题描述】:

在 python 和 pandas 中使用 sqlite3 时出现意外错误。我正在使用 sqlite 数据库进行分析,因此它是单用户、单计算机。我在 Python 3.9.1 中,使用 sqlite 3.33.0 和 pandas 1.2.1。

简短的描述是,我正在尝试遍历Table1 的行,并且对于每一行,使用存储在Table1 中的ID 根据API 请求将数据插入Table2。 API 为我提供了比 Table2 需要的更多列,因此我执行以下操作将其插入新的临时表,然后将我需要的列复制到 Table1

my_dataframe.to_sql("tmp", conn, if_exists="replace", index=False)
cur.execute("INSERT INTO Table1 (col1, col2) SELECT col1, col2 FROM Table2")

问题是,在循环的第二次迭代中,当 pandas 尝试删除 tmp 表时出现错误。完整代码如下:

def get_data(api_id, conn):
    my_dataframe = call_to_api(api_id)
    my_dataframe.to_sql("tmp", conn, if_exists="replace", index=False)
    cur.execute("INSERT INTO Table1 (col1, col2) SELECT col1, col2 FROM Table2")

for chunk in pd.read_sql_query("SELECT id_for_api FROM Table1", conn, chunksize=10):
    ids = chunk["id_for_api"].values

    for api_id in ids:
        get_data(api_id, conn)

我得到的错误是:

DatabaseError: Execution failed on sql 'DROP TABLE "tmp"': database table is locked

这是由这一行提出的:

pd.DataFrame(data).to_sql("tmp", conn, if_exists="replace", index=False)

我已经尝试了我能想到的一切来解决这个问题:

  • 将连接更改为isolation_level=None(自动提交)
  • INSERT 语句后添加conn.commit()
  • get_data 函数 (cur = conn.cursor()) 中创建新光标
  • 使用read_sql_query (conn2 = sqlite3.connect('mydb.db')) 创建一个新连接以用于外部循环

我错过了什么?关于 sqlite 隔离级别或锁定有什么我不明白的地方吗?

【问题讨论】:

  • 有没有想过这个问题?进入我的第二天试图让这个工作。
  • @jseals,很遗憾没有。我作为一种解决方法所做的只是从第一个表中查询我需要的所有行(而不是在循环中),将它们放入 Python 列表中,然后使用该 Python 列表来构造我对第二个表的查询。这并不理想,但我必须继续前进,这对我的项目很有效。

标签: python pandas database sqlite


【解决方案1】:

当你建立连接时,设置autocommit=True

@contextlib.contextmanager
def database_connect():
    db_conn = pyodbc.connect(
        autocommit=True,  # needed to prevent locks in DB with SPs
    )
    try:
        yield db_conn
    finally:
        db_conn.close()
...
    with database_connect() as db_conn:
        df = pd.read_sql_query(
            f"EXEC {sp_table}.{sp_name} " + ",".join(f"@{a}=?" for a in kwargs.keys()),
            db_conn,
            params=kwargs.values()
        )

【讨论】:

    猜你喜欢
    • 2019-10-07
    • 2011-10-30
    • 1970-01-01
    • 1970-01-01
    • 2011-08-05
    • 2015-05-11
    • 2011-02-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多