
本文介绍如何将格式化的 sql 查询输出字符串(含表头与多行数据)高效、健壮地转换为 python 字典列表,兼容 python 2 与 python 3,并支持空格分隔的字段解析。
本文介绍如何将格式化的 sql 查询输出字符串(含表头与多行数据)高效、健壮地转换为 python 字典列表,兼容 python 2 与 python 3,并支持空格分隔的字段解析。
在实际开发中,尤其在轻量脚本或数据库调试场景下,我们常遇到直接执行 SQL 后返回的纯文本格式结果——例如 psql -t 或某些 ORM 的原始输出。这类字符串通常包含表头行、分隔线(如 =============),以及后续多行数据,字段间以空格分隔。目标是将其结构化为标准的 Python 对象数组(即 list[dict]),便于后续 JSON 序列化、Pandas 加载或 API 响应。
以下是一个典型输入示例:
text = 'enable id \n =============\nf avc-qwqwq\nt abd-rrtrtr\n f rec-yyuyu \n'
期望输出为:
[
{'enable': 'f', 'id': 'avc-qwqwq'},
{'enable': 't', 'id': 'abd-rrtrtr'},
{'enable': 'f', 'id': 'rec-yyuyu'}
]✅ 推荐方案:使用 splitlines() + zip() 构建字典列表(Python 3)
该方法简洁、可读性强,利用解包语法精准跳过分隔行:
text = 'enable id \n =============\nf avc-qwqwq\nt abd-rrtrtr\n f rec-yyuyu \n'
# 按行分割,解包:第一行为 header,第二行为分隔线(丢弃),其余为数据行
header_str, _, *rows_str = text.splitlines()
# 提取列名(自动忽略多余空格)
header = header_str.split() # → ['enable', 'id']
# 逐行解析:对每行调用 split() 分割字段,再用 zip(header, fields) 构建键值对,转为 dict
objs = [dict(zip(header, row_str.split())) for row_str in rows_str if row_str.strip()]
print(objs)
# [{'enable': 'f', 'id': 'avc-qwqwq'}, {'enable': 't', 'id': 'abd-rrtrtr'}, {'enable': 'f', 'id': 'rec-yyuyu'}]⚠️ 注意:row_str.split() 默认按任意空白符(空格、制表符、连续空格)分割并自动过滤空字符串,因此能稳健处理 ' f rec-yyuyu ' 这类首尾含空格的行。
? 兼容 Python 2 的写法(无解包语法支持)
Python 2 不支持 *rows_str 解包语法,需改用迭代器显式消费前两行:
text = 'enable id \n =============\nf avc-qwqwq\nt abd-rrtrtr\n f rec-yyuyu \n' lines = text.splitlines() iter_lines = iter(lines) header_str = next(iter_lines) # 第一行:表头 _ = next(iter_lines) # 第二行:分隔线(丢弃) rows_str = list(iter_lines) # 剩余所有行 header = header_str.split() objs = [dict(zip(header, row.split())) for row in rows_str if row.strip()] print(objs)
该写法在 Python 2.7+ 和 Python 3.x 中均能正常运行,是跨版本脚本的推荐实践。
? 关键注意事项与增强建议
- 空行/空白行处理:务必添加 if row.strip() 过滤,避免因末尾换行或空行导致 dict(zip(...)) 生成空字典;
-
字段数量不一致? 若某行字段数 ≠ 表头数,zip() 会截断至最短长度——建议增加校验:
for row_str in rows_str: fields = row_str.split() if len(fields) != len(header): raise ValueError(f"Row mismatch: expected {len(header)} fields, got {len(fields)}: '{row_str}'") objs.append(dict(zip(header, fields))) - 非空格分隔? 如字段含空格(如 "John Doe")、或使用固定列宽/制表符,请改用 re.split(r'\s{2,}', row_str) 或 csv.reader(StringIO(row_str), delimiter='\t');
- SQL 列名含空格? 当前逻辑不支持(如 'user name')。若存在,应先用正则提取列名,或改用 pandas.read_csv(StringIO(text), sep=r'\s+', skiprows=1, skipfooter=1, engine='python')。
✅ 总结
将 SQL 文本结果转为对象数组的核心在于三步:
1️⃣ 准确切分:用 splitlines() 获取逻辑行,跳过表头与分隔线;
2️⃣ 规范解析:用 str.split() 安全提取字段(自动去空格、去空项);
3️⃣ 结构映射:用 zip(header, fields) + dict() 实现行列对齐。
该方案轻量、无外部依赖、跨版本兼容,是处理简单 SQL 文本输出的首选模式。对于复杂格式,建议升级至 pandas 或专用 SQL 解析库。










