python给pymysql批量构造数据 - 关于KeyError报错

前言

        先前我们使用了mysql包里的游标去执行cursor.execute(sql语句),能够在测试站的数据库中构造出大量的数据来为我们的测试提高效率。但是在这几天的工作当中遇到了一个之前构造数据没有遇到过的问题,因为报错处理了很久,其实最后就是一个简单的语法知识,在这里记录一下算是提醒自己对基础知识和概念一定要足够扎实吧。

1.报错

        首先,我们还是套用先前的框架,这里涉及到隐私我就不加上前面创建连接数据库对象里的信息了,直接看底下创建游标对象部分的代码。

# 创建游标
cursor = conn.cursor()

# 从navicat工具里复制具体的插入语句,将其赋值给sql1变量名

sql1 = "INSERT INTO `kk_monitor`.`jk_alarm_logs` (`id`, `alarm_way`, `alarm_user_id`, \
`ip`, `task_id`, `rule_id`, `point_id`, `alarm_rules`, `status`, `created_at`, `updated_at`\
, `deleted_at`, `alarm_time`, `recover_time`, `is_old_data`) \
VALUES ('{}', '1', '19', '0.0.0.0', {}, 1, 1, '{\"type\":\"1\",\"period\":\"3\",\"compare\":\">=\",\"value\":150}', 2, '2022-09-15 15:48:42', '2022-09-15 15:48:45', NULL, '2022-09-14 15:48:49', NULL, 0);"


# 循环遍历 构造三条测试数据记录
id = 1000000
for i in range(3):
    id += i
    task_id = 1000000+i
    cursor.execute(sql1.format(id,task_id))


# 提交事务处理,关闭游标,关闭连接
conn.commit()
cursor.close()
conn.close()

        能够通过代码段看得出来和先前构造10w条数据的博客里的代码几乎是一致的,那么问题出在了哪里?我们先来看下报错的提示:

         回溯到上面的脚本里发现了这个报错的地方出现在了对数据库进行数据增添的insert语句当中,但是一脸懵逼,明明这个部分的语句都是我们先前一样的脚本啊,怎么这里不行了呢?为什么从navicat里复制出来的insert语句在这里作为字符串却报错了。再来看看我们insert语句当中有没有哪里是不同的,果然有个键值和其他类型的不太一样。

        我们看到了这么一个值:

'{"type":"1","period":"3","compare":">=","value":150}'

        问题来了,这个值确实不能作为字典里的数据形式怎么办?

2.解决

        首先,根据报错提示能想的到也是和字典相关,但是我们一个整体的sql1变量已经定义是字符串类型,那么我们在原来的基础上能不能使用什么方法不改变这个部分的内容然后又把它保留呢?

        很简单,我们可以使用一个变量定义一个字符串类型的东西嘛,然后再使用双引号把它引进去这样不就实现了?这时候我的代码变成了

alarm_role='{"type":"1","period":"3","compare":">=","value":150}'

sql1 = "INSERT INTO `kk_monitor`.`jk_alarm_logs` (`id`, `alarm_way`, `alarm_user_id`, \
`ip`, `task_id`, `rule_id`, `point_id`, `alarm_rules`, `status`, `created_at`, `updated_at`\
, `deleted_at`, `alarm_time`, `recover_time`, `is_old_data`) \
VALUES ('{}', '1', '19', '0.0.0.0', {}, 1, 1, "+alarm_role+", 2, '2022-09-15 15:48:42', '2022-09-15 15:48:45', NULL, '2022-09-14 15:48:49', NULL, 0);"

id = 1000000
for i in range(3):
    id += i
    task_id = 1000000+i
    cursor.execute(sql1.format(id,task_id))

        但是结果又给我报了一模一样的错误。。。。我还去检验了一下是不是我忘记做字符类型的数据转换了,但是这里发现明明就是字符类型,为什么又给我返回这样的错误。

         我不信邪,我又换了一种形式,为了替换这里的固定值,考虑了用format函数一样的形式,把这里的alarm_role在cursor.execute(sql1.format(id,task_id,alarm_role)里执行就好,然后还是这样的错误,实在是当局者迷旁观者清去问了一下同学是不是和数据库表结构设计有关,因为我对这方面确实不太清楚。

        结果人家随口说了句你是不是变量语法错了,我赶紧回去检查了一下发现确实是和语法有关。。。

        我最后的代码里还写着"+alarm_role+",实际上这个还是和第二次改的一样,其实把这个换掉换成{}就好了,因为alarm_role已经是相当于全局变量了,那么我最后成功的代码就如下图所示,也终于可以正常输出了。

alarm_role='{"type":"1","period":"3","compare":">=","value":150}'

sql1 = "INSERT INTO `kk_monitor`.`jk_alarm_logs` (`id`, `alarm_way`, `alarm_user_id`, \
`ip`, `task_id`, `rule_id`, `point_id`, `alarm_rules`, `status`, `created_at`, `updated_at`\
, `deleted_at`, `alarm_time`, `recover_time`, `is_old_data`) \
VALUES ('{}', '1', '19', '0.0.0.0', {}, 1, 1, '{}', 2, '2022-09-15 15:48:42', '2022-09-15 15:48:45', NULL, '2022-09-14 15:48:49', NULL, 0);"

id = 1000000
for i in range(3):
    id += i
    task_id = 1000000+i
    cursor.execute(sql1.format(id,task_id,alarm_role))

conn.commit()

cursor.close()
conn.close()

总结

        就是一个小小的细微的问题,其实还困扰了我蛮久的。思路是没有错的,错的就在于不够细心,也是因为代码抛出异常经验积累的太少,这种又不像是能用断点判断出来流程的问题,属于是语法的问题,还是得多手撕代码。希望如果之后也遇到像 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值