如何使用 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