如何使用 executemany 处理异常(MySQL 和 Python)

Posted

技术标签:

【中文标题】如何使用 executemany 处理异常(MySQL 和 Python)【英文标题】:How to handle exception with executemany (MySQL and Python) 【发布时间】:2019-05-05 09:04:07 【问题描述】:

我有一个使用 executemany 将行批量插入 mysql 表的 python 脚本。数据是从不同的 API 中检索出来的,所以时不时会有意外的数据导致一行导致异常。

如果我理解正确 - 当调用 1,000 行的 executemany 并且其中一个有问题时 - 不会插入整个批量。

我想找到一种方法来提交 1,000 条记录并成功加载没有问题的记录。例如 - 如果一千个中的一个有问题,它将不会被加载,但所有其他 999 都会被加载。

这方面的最佳做法是什么?我正在考虑捕获一个异常并创建一个后备以重新提交所有 1000 个 - 但似乎必须有更好的方法来实现相同的结果。

建议?

【问题讨论】:

您遇到了哪些例外情况?是什么让您认为重试会起作用? 如果例如在一批 1000 条记录中只有 364 条记录有问题 - 我想重新尝试单独插入所有其他 999 条记录。因为我不知道是哪条记录导致了异常,而且我因为一个异常使整个批次都失败了——我正在考虑将所有 1000 条语句作为单个语句重试(执行而不是执行多个语句)。异常可能来自空 PK 字段、意外编码等。 是的,重试会将错误范围缩小到最少的行数。 【参考方案1】:

插入时,executemany 将所有数据行批处理在一起,并尝试用一个命令将它们全部插入。据我所知,没有办法在不破坏整批插入的情况下处理一次失败插入引发的异常。如果一行失败,则整个命令失败。

这是它的样子(示例取自MySQL docs)。如果你告诉它这样做:

data = [
  ('Jane', date(2005, 2, 12)),
  ('Joe', date(2006, 5, 23)),
  ('John', date(2010, 10, 3)),
]
stmt = "INSERT INTO employees (first_name, hire_date) VALUES (%s, %s)"
cursor.executemany(stmt, data)

executemany 会这样做:

INSERT INTO employees (first_name, hire_date)
VALUES ('Jane', '2005-02-12'), ('Joe', '2006-05-23'), ('John', '2010-10-03')

如果您认为这将是一种罕见的情况,那么您单独重试每个插入的想法将会奏效。比如:

try:
    cursor.executemany(stmt, data)
except ___Error:  # fill in the blank
    for datum in data:
        try:
            cursor.execute(stmt, datum)
        except ___Error:
            # handle exception, eg print warning
            ...

如果您认为这将是一个常见问题,那么放弃executemany 并直接执行此操作可能会更高效:

for datum in data:
    try:
        cursor.execute(stmt, datum)
    except ___Error:
        # handle exception, eg print warning
        ...

【讨论】:

【参考方案2】:

在“executemany”查询的开头执行“INSERT OR IGNORE”语句可以让您完全做到这一点 - 它只会添加不会带来错误的值。

唯一的缺点是您再也看不到发生了什么错误。 例如,

原始数据库:

('kaushik', 3)
('maria', 4)
('shreya', 38)

查询:(在python中)

listofnames = [
('kaushik', 3),
('maria', 4),
('jane', 56)
]

c.executemany("INSERT OR IGNORE INTO bob (name, number) VALUES (?,?)", 
listofnames)

最终数据库:

('kaushik', 3)
('maria', 4)
('shreya', 38)
('jane', 56)

【讨论】:

以上是关于如何使用 executemany 处理异常(MySQL 和 Python)的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 MySQL executemany 更新 Python 中的列表列表?

如何使用 executemany 将每个 Key 中的第一个值写入数据库

如何在 9.414 版本中使用 executemany 忽略 postgres 中的重复项?

如何使用 executemany 将 Python 中的字典列表插入 MySQL

如何从字典中选择多行(executemany select)

如何通过 executemany() 语句转换 pandas 数据框以进行插入?