PyMySQL升级至v1.1.1后Cursor.execute参数格式化异常求助
PyMySQL 1.1.1参数格式化SQL错误问题及解决办法
问题背景
将环境迁移至新venv并把PyMySQL从v1.1.0升级到v1.1.1后,使用Cursor.execute格式化参数时出现SQL语法错误,尤其涉及numpy浮点类型和普通浮点类型的参数处理异常。
查询场景示例
client_id = float(2) params = (client_id) print(f"Parameters :\n\t{params}") try: cursor.execute("SELECT * FROM clients WHERE id = %s", params) except: print("EXCEPTION") print(f"Query :\n\t{cursor._executed}")
执行输出:
Parameters : (2.0) Query : SELECT * FROM clients WHERE id = 2.0e0
此场景仅参数被转为科学计数法,不影响查询,但插入/更新场景会直接报错。
更新场景示例
client_id = float(2) balance = np.float64(1000) params = (client_id, balance) print(f"Parameters :\n\t{params}") try: cursor.execute("UPDATE client_balances SET balance = %s WHERE client_id = %s", params) except: print("EXCEPTION") print(f"Query :\n\t{cursor._executed}")
执行输出:
Parameters : (2.0, np.float64(1000.0)) EXCEPTION Query : UPDATE client_balances SET balance = np.float64(1000)e0 WHERE client_id = 2.0e0
触发异常:
ProgrammingError - (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'e0, balance = np.float64(1000)e0, WHERE client_id = 2.0e0' at line 1")
临时解决方案(不推荐)
手动将参数转为字符串可正常执行,但存在类型转换开销和潜在精度问题:
client_id = float(2) balance = np.float64(1000) params = (client_id, balance) print(f"Parameters :\n\t{params}") refactored_params = [] for param in params: refactored_params.append(str(param)) try: cursor.execute("UPDATE client_balances SET balance = %s WHERE client_id = %s", refactored_params) except: print("EXCEPTION") print(f"Query :\n\t{cursor._executed}")
执行输出:
Parameters : (2.0, np.float64(1000.0)) Query : UPDATE client_balances SET balance = '1000' WHERE client_id = '2.0'
合理解决办法
1. 转换参数为原生Python类型
PyMySQL 1.1.1对非原生数值类型(如np.float64)的处理逻辑存在问题,需将其转换为原生Python数值类型:
client_id = int(float(2)) # 若id为整数类型,直接转int更合适 balance = float(np.float64(1000)) params = (client_id, balance) cursor.execute("UPDATE client_balances SET balance = %s WHERE client_id = %s", params)
此方式让PyMySQL正确识别参数类型,生成合法的SQL语句。
2. 自定义通用参数转换函数
避免手动逐个转换,编写通用函数处理numpy数值类型:
import numpy as np def normalize_params(params): converted = [] for param in params: # 处理所有numpy数值类型 if isinstance(param, np.number): converted.append(param.item()) else: converted.append(param) return tuple(converted) # 使用示例 client_id = float(2) balance = np.float64(1000) params = (client_id, balance) cursor.execute("UPDATE client_balances SET balance = %s WHERE client_id = %s", normalize_params(params))
这个函数自动将numpy数值转为原生Python类型,适配所有参数场景,比手动转字符串高效且安全。
3. 验证版本差异与bug状态
检查PyMySQL 1.1.1的更新日志,确认是否为已知bug。如果是官方引入的问题,可临时降级至1.1.0,或等待官方修复版本发布。但降级需权衡版本兼容性,优先推荐前两种方案。
内容的提问来源于stack exchange,提问作者Arkaik
相关产品推荐
相关产品推荐

