一、 功能概述
一个专注于数据提取与重组的python脚本工具。其核心使命是自动化地从一个名为 results.json的源数据文件中,批量提取出名为 output的特定字段的值,并将这些值重新封装到一个结构化的新文件 outputs.json中。
可以将其理解为数据流水线中的一个 “字段提取器” 或 “数据蒸馏器”。它解决了一个常见的数据处理痛点:当从一个包含多维信息的复杂数据源(results.json)中,只关心某一个特定维度的数据(output字段)用于后续分析、可视化或报告时,手动复制粘贴效率低下且易出错。此脚本通过编程方式,实现了该过程的批量化、自动化与标准化。
核心功能拆解:
- 数据读取:安全地读取并解析json格式的源文件(
./results.json)。 - 目标字段提取:遍历源数据中的所有条目,精准定位并收集每个条目下的
output字段值。 - 数据重组:将收集到的所有
output值,按照预定义的新结构(一个包含outputs键的字典)进行封装。 - 数据持久化:将重组后的数据以格式化的json形式写入一个新的目标文件(
./outputs.json)。 - 状态反馈与错误处理:在控制台输出操作结果(如成功提取的数量)或捕获并报告运行时可能出现的各种异常(如文件不存在、格式错误等)。
二、 代码结构与执行流程分析
程序采用经典的python脚本结构,清晰明了。
1.入口与执行逻辑 (if __name__ == “__main__”:):这是python模块的标准执行入口。它检查当前脚本是否被直接运行(而非作为模块导入)。当直接运行 python tiqu.py时,条件成立,随即调用 extract_outputs()函数,启动整个提取流程。这种设计增强了代码的模块性,使得 extract_outputs函数既可以被独立脚本调用,也可以在将来被其他模块导入和复用。
2.核心函数 extract_outputs():这是脚本的“大脑”,所有主要逻辑都封装在此函数内。函数内部采用了“尝试-异常(try-except)”的防御式编程结构,确保了程序的健壮性。
标准执行流(无异常发生):
步骤1:文件读取与解析
with open(‘./results.json’, ‘r’, encoding=‘utf-8’) as file:使用上下文管理器打开文件。这是一种最佳实践,它能确保无论在代码块中是否发生异常,文件都会被正确关闭,避免资源泄漏。指定 utf-8编码确保了其对多语言文本(如中文)的良好支持。
data = json.load(file):调用 json模块的 load函数,将文件对象反序列化为python原生数据结构(通常是列表或字典)。
步骤2:数据提取
outputs_list = [item.get(‘output’, ‘’) for item in data]:这是整个脚本的算法核心。它使用列表推导式,一种简洁高效的python语法,遍历 data中的每一个 item。对于每个 item,使用 .get(‘output’, ‘’)方法安全地获取 output键对应的值。如果键不存在,则返回一个空字符串 ’’作为默认值,防止程序因 keyerror而崩溃。所有获取到的值被收集到一个新的列表 outputs_list中。
步骤3:数据结构重组
output_data = {“outputs”: outputs_list}:创建一个新的字典 output_data。其唯一键是字符串 “outputs”,对应的值就是上一步中提取出的所有 output值组成的列表。这个步骤完成了从原始结构到目标结构的转换。
步骤4:数据写入
再次使用 with open上下文管理器,以写入模式 (‘w’) 打开(或创建)./outputs.json文件。
json.dump(output_data, file, ensure_ascii=false, indent=2):将 output_data字典序列化为json字符串并写入文件。
ensure_ascii=false:允许非ascii字符(如中文)直接以其原样(如unicode)写入文件,而不是被转义为\uxxxx的形式,使得生成的文件对人类更可读。indent=2:使用2个空格进行缩进,生成格式美观、具有层级结构的json文件,便于人工查阅和调试。
步骤5:成功反馈
print(f“成功提取 {len(outputs_list)} 个output字段到outputs.json文件”):使用f-string格式化字符串,向用户报告成功信息,并告知提取的具体数量,提供了明确的操作反馈。
3.异常处理流程 (except块):
程序预见了三种常见错误,并按优先级从具体到一般进行捕获:
filenotfounderror:最可能发生的错误,即源文件results.json不存在于指定路径。给出明确错误提示。json.jsondecodeerror:源文件存在,但其内容不符合json语法规范,无法解析。同样给出明确提示。exception as e:这是一个“兜底”的异常捕获,处理所有其他未预见的运行时错误。通过print(f“发生错误:{e}”)打印具体的异常信息,有助于高级调试。
三、 数据结构设计
本程序涉及两个核心数据结构:输入的源数据结构和输出的目标数据结构。
1.源数据(results.json)的假设结构:
从代码 [item.get(‘output‘, ’’) for item in data]可以推断,程序预期 data是一个可迭代对象,通常是一个列表(list)。
列表中的每个 item预期是一个字典(dict)。
每个 item字典中可能包含一个名为 “output”的键。该键对应的值可以是任何json支持的类型,如字符串、数字、布尔值、数组、对象等,但根据程序上下文,通常可能是字符串或数组。
示例假设结构:
[
{"id": 1, "input": "问题a", "output": "答案a", "score": 0.95},
{"id": 2, "input": "问题b", "output": "答案b", "score": 0.87},
{"id": 3, "input": "问题c", "score": 0.92}, // 此条目无output键
...
]2.目标数据(outputs.json)的结构:
程序创建了一个全新的、高度聚焦的数据结构。它是一个字典,仅包含一个键值对。
这种结构极其简洁,去除了所有无关字段,使得下游应用可以毫无负担地直接使用 outputs列表。
键:固定为字符串 “outputs”。
值:一个列表,其元素顺序与源数据 data中的条目顺序严格一致。列表中每个元素就是对应源条目中 output键的值。如果源条目中没有 output键,则对应位置是一个空字符串 ’’。
承接上例,生成的 outputs.json内容为:
{
"outputs": ["答案a", "答案b", ""]
}四、 算法、编程思想与关键技术
1.列表推导式:这是python中实现map和filter功能的精妙语法糖。[item.get(‘output‘, ’’) for item in data]一行代码等价于一个for循环,但更简洁、执行效率也通常更高。它清晰地表达了“从一个集合中映射出另一个集合”的语义。
2.防御性编程与健壮性设计:
- 异常处理:全面的
try-except块是程序稳定性的基石。它区分了不同类型的错误,并提供了友好的用户提示,避免了程序因外部因素(文件缺失、格式错误)而崩溃。 - 安全的字典访问:使用
.get(key, default)方法而非直接通过item[‘output’]索引访问。这是处理可能存在缺失键的字典时的最佳实践,避免了潜在的keyerror,并通过提供默认值(空字符串)保证了输出列表长度的确定性和一致性。
3.上下文管理器:通过with open() as file:语句管理文件资源。这确保了即使在读写文件过程中发生异常,文件也能被正确关闭,资源得到及时释放,避免了数据损坏或资源锁定的问题。
4.数据序列化与反序列化:熟练运用python内置的json模块进行load(从文件到对象)和dump(从对象到文件)操作,是实现程序与json文件这种通用数据格式交互的关键。
5.函数式封装:将主要逻辑封装在extract_outputs()函数中,并通过if __name__ == “__main__“:来调用,体现了“模块化”的编程思想。这提高了代码的可读性、可测试性和可复用性。
五、 潜在应用场景与扩展方向
典型应用场景:
- 机器学习/ai实验日志处理:
results.json可能是一次模型批量推理的结果日志,包含输入、模型输出、置信度分数等。本脚本用于单独提取所有“模型输出”,用于后续的人工评估或自动评测。 - api响应批量提取:当批量调用某个api并将所有响应保存到一个json文件后,可以使用此脚本从每个响应体中提取出核心的
output或data字段。 - 数据清洗与预处理管道:在etl流程中,作为中间环节,从复杂的半结构化数据中抽取出所需的标准字段。
- 报告生成:从详细的原始数据中提取关键指标或结论,生成一个简洁的数据源,供图表生成工具使用。
扩展与改进方向:
增强灵活性:
- 参数化:通过命令行参数(如
argparse库)或配置文件,允许用户指定输入/输出文件路径、目标字段名(不硬编码为output)、默认值等。 - 多字段提取:扩展为可以同时提取多个指定字段,并组织成更复杂的结构(如列表套字典)。
提升性能:对于非常大的json文件(gb级别),可以考虑使用ijson等流式解析库,以迭代方式处理,避免一次性加载全部数据到内存。
增强功能:
- 过滤条件:在提取时加入条件判断,例如只提取
score大于某阈值的output。 - 数据转换:在提取过程中对
output值进行简单的清洗或转换(如去除首尾空格、类型转换)。
增强鲁棒性与日志:
- 更精细的异常处理,例如区分文件权限错误、磁盘空间不足等。
- 使用
logging模块替代print语句,实现不同级别(info, warning, error)的日志记录,便于在后台长期运行或集成到系统中时进行监控。
六、 代码质量与风格评估
优点:
- 结构清晰:函数封装和入口判断使代码结构良好。
- 可读性强:变量名具有描述性(如
outputs_list,output_data),注释虽然简单但指明了关键部分。 - 健壮性好:全面的异常处理和安全的字典访问方法。
- 符合规范:使用上下文管理器、指定文件编码等,符合python编程的最佳实践。
可考虑优化的点:
- 路径硬编码:输入输出文件路径硬编码在代码中。在生产环境中,建议通过参数或配置外部化。
- 单一次任务:当前脚本功能单一。虽然这是其设计目的,但作为示例,可以考虑提及如何扩展为更通用的工具。
- 默认值选择:使用空字符串
’’作为缺失键的默认值。这在某些场景下是合理的,但并非万能。如果output字段本身预期是数字或复杂对象,空字符串可能不合适。根据具体业务逻辑选择默认值(如none)可能更优。
总结
一个设计精良、功能聚焦、具备工业级健壮性的小型数据提取工具。它完美地诠释了“单一职责原则”,将“从json列表中提取指定字段”这一任务完成得高效而可靠。其代码体现了现代python编程的诸多优秀实践,包括上下文管理、防御性编程、安全的字典操作、结构化的异常处理以及清晰的数据转换逻辑。尽管在灵活性和扩展性上有其局限,但作为解决特定问题的专用脚本,它是一个非常出色的范本,并且其核心思想和代码结构可以轻松地被借鉴和扩展以适应更复杂的数据处理需求。通过参数化、功能增强和性能优化,它可以成长为一个功能强大的通用数据提取实用程序。
源代码
import json
def extract_outputs():
try:
# 读取results2.json文件
with open('./results.json', 'r', encoding='utf-8') as file:
data = json.load(file)
# 提取所有output字段内容
outputs_list = [item.get('output', '') for item in data]
# 创建新的数据结构
output_data = {
"outputs": outputs_list
}
# 写入outputs.json文件
with open('./outputs.json', 'w', encoding='utf-8') as file:
json.dump(output_data, file, ensure_ascii=false, indent=2)
print(f"成功提取 {len(outputs_list)} 个output字段到outputs.json文件")
except filenotfounderror:
print("错误:找不到results2.json文件")
except json.jsondecodeerror:
print("错误:results2.json文件格式不正确")
except exception as e:
print(f"发生错误:{e}")
if __name__ == "__main__":
extract_outputs()到此这篇关于python脚本实现json数据提取与重组工具的文章就介绍到这了,更多相关python json数据提取与重组内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论