在Python开发场景中,经常需要从嵌套字典中提取数据生成SQL插入语句,如果字典存在键缺失的情况,直接取值就会抛出KeyError异常,导致程序中断。因此需要设计合理的键缺失处理策略,保障SQL插入语句构建过程的稳定性。

常见嵌套字典键缺失场景
假设我们需要从接口返回的嵌套字典中提取用户数据,生成插入用户表的SQL语句,字典结构可能如下:
user_data = {
"name": "张三",
"info": {
"age": 25,
# 缺失gender键
"contact": {
"phone": "13800138000"
# 缺失email键
}
}
}
如果直接通过user_data["info"]["gender"]的方式取值,就会触发KeyError,因此必须先处理键缺失的情况。
键缺失处理核心策略
1. 使用字典get方法设置默认值
字典的get(key, default)方法可以在键不存在时返回默认值,不会抛出异常,适合处理单层键缺失的场景。
# 获取存在的键
name = user_data.get("name", "")
# 获取不存在的键,返回默认值空字符串
gender = user_data.get("info", {}).get("gender", "")
print(name) # 输出:张三
print(gender) #输出:
2. 递归处理多层嵌套字典键缺失
当嵌套层级较多时,逐层调用get方法代码冗余,可以封装一个递归函数,统一处理多层嵌套的键缺失问题。
def get_nested_value(data, keys, default=None):
"""
递归获取嵌套字典的值
:param data: 嵌套字典
:param keys: 键路径列表,如["info", "contact", "email"]
:param default: 键不存在时的默认值
:return: 对应键的值或默认值
"""
current = data
for key in keys:
if isinstance(current, dict) and key in current:
current = current[key]
else:
return default
return current
# 测试获取多层嵌套不存在的键
email = get_nested_value(user_data, ["info", "contact", "email"], "")
phone = get_nested_value(user_data, ["info", "contact", "phone"], "")
print(email) # 输出:
print(phone) # 输出:13800138000
3. 提前校验键存在性
如果某些键是SQL插入语句的必填字段,缺失时需要提前抛出异常提示,避免生成不完整的SQL语句。
required_keys = [
["name"],
["info", "age"],
["info", "contact", "phone"]
]
for keys in required_keys:
value = get_nested_value(user_data, keys)
if value is None or value == "":
raise ValueError(f"必填字段{'->'.join(keys)}缺失,无法生成SQL插入语句")
构建健壮SQL插入语句
结合上述键缺失处理策略,我们可以安全地提取嵌套字典中的数据,构建完整的SQL插入语句,同时避免SQL注入风险,使用参数化查询的方式。
import sqlite3
# 提取所有需要的字段,设置默认值
insert_data = {
"name": get_nested_value(user_data, ["name"], ""),
"age": get_nested_value(user_data, ["info", "age"], 0),
"gender": get_nested_value(user_data, ["info", "gender"], "未知"),
"phone": get_nested_value(user_data, ["info", "contact", "phone"], ""),
"email": get_nested_value(user_data, ["info", "contact", "email"], "")
}
# 构建参数化SQL插入语句
sql = """
INSERT INTO user (name, age, gender, phone, email)
VALUES (?, ?, ?, ?, ?)
"""
params = (
insert_data["name"],
insert_data["age"],
insert_data["gender"],
insert_data["phone"],
insert_data["email"]
)
# 执行SQL(示例用sqlite3演示)
conn = sqlite3.connect("test.db")
cursor = conn.cursor()
# 先创建表(实际项目中表已存在可省略)
cursor.execute("""
CREATE TABLE IF NOT EXISTS user (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT,
age INTEGER,
gender TEXT,
phone TEXT,
email TEXT
)
""")
cursor.execute(sql, params)
conn.commit()
conn.close()
上述方式既处理了嵌套字典的键缺失问题,又通过参数化查询避免了SQL注入,同时必填字段的校验也保障了插入数据的完整性,整体提升了SQL插入语句构建过程的健壮性。
注意事项
- 默认值的选择要和数据库字段类型匹配,比如整数类型字段默认值设为0,字符串类型设为空字符串,避免类型不匹配报错。
- 如果嵌套字典的结构不固定,建议先打印字典结构确认键路径,避免出现路径错误的问题。
- 生产环境中可以对缺失的非必填字段做日志记录,方便后续排查数据问题。