python
复制代码
# -*- coding: utf-8 -*-
"""
@Created on : 2026/5/6 10:03
@creator : er_nao
@File :Day_15.py
@Description :json文件读取与写入
"""
import jieba
import json
import os
""" 核心知识点 1:JSON 文件读取进阶用法 """
# 进阶用法 1:批量读取文件夹里的所有 JSON 文件(NLP 批量处理核心)
# ------------------ 核心配置 ----------------
# 存放JSON文件的文件夹路径(替换成你自己的文件夹路径)
JSON_FOLDER = 'C:\\Users\\hp\\Desktop\\json_file'
# 筛选条件:只读取.json结尾的文件
FILE_SUFFIX = '.json'
def batch_read_json_file(folder_path, file_suffix):
"""
批量读取文件夹里的所有JSON文件,返回合并后的所有数据
:param folder_path: JSON文件所在的文件夹路径
:param file_suffix: 要筛选的文件后缀,比如.json
:return: 合并后的所有JSON数据列表
"""
# 存储所有读取到的json数据
all_json_data =[]
# 遍历文件夹里的所有文件
for filename in os.listdir(folder_path):
# 只处理制定后缀的文件
if filename.endswith(file_suffix):
# 拼接完整的文件路径
file_path = os.path.join(folder_path, filename)
try:
# 读取json文件
with open(file_path,'r',encoding='utf-8') as f:
json_data = json.load(f)
if isinstance(json_data,list):
all_json_data.append(json_data)
else:
all_json_data.append(json_data)
print(f"成功读取文件:{filename}")
except Exception as e:
print(f"读取文件失败:{filename},错误原因:{e}")
# 返回所有合并后的数据
return all_json_data
# ---------------------- 主程序:批量读取 + 简单统计 ----------------------
# if __name__ == '__main__':
# # 批量读取所有JSON文件
# all_chat_data = batch_read_json_file(JSON_FOLDER, FILE_SUFFIX)
#
# # 简单统计结果
# print(f"\n 批量读取完成!")
# print(f"总读取文件数:{len(os.listdir(JSON_FOLDER))}")
# print(f"总读取到的对话轮数:{len(all_chat_data)}")
#
# # 打印前两条数据,验证读取结果
# if len(all_chat_data) > 0:
# print("\n 前两条读取到的内容结果")
# for i, chat in enumerate(all_chat_data[:2]):
# print(f"第{i+1}条:{chat}")
# 进阶用法 2:大 JSON 文件流式读取(避免内存溢出,NLP 大语料处理核心)
# ---------------------- 核心配置 ----------------------
# 大JSON文件路径(替换成你自己的大文件路径)
BIG_JSON_FILE = '/mnt/nlp_corpus.jsonl'
# 停用词列表
STOP_WORDS = ["的", "是", "在", "和", "有", "也", "就", "都", "而", "及", "与", "着", ",", "。", "!", "?", ";", ":", "、", " "]
# ---------------------- 大JSON文件流式读取 + 处理 ----------------------
def stream_read_big_json(file_path):
"""
流式读取大JSON文件(行级JSON格式),每读取一行就处理一行
:param file_path: 大JSON文件路径
:return: 处理后的所有语料数据
"""
# 存储处理后的结果
processed_corpus = []
with open(file_path, 'r',encoding="utf-8") as f:
for line_num,line in enumerate(f,start=1):
line = line.strip()
if not line:
continue
try:
# 把当前行的json字符串,转换成python字典
json_data = json.loads(line)
# 提取语料文件
text = json_data.get('text','')
if not text:
continue
# ---------------------- 对文本做NLP处理 ----------------------
# 1.清洗文本
clean_text = text.strip().replace(' ','')
# 2.分词+过滤停用词
words = jieba.lcut(clean_text)
valid_words = [word for word in words if word not in STOP_WORDS and word.strip()!=""]
# 把处理后的结果添加到列表里
processed_data = {
"行号": line_num,
"原始文本": text,
"清洗后的文本": clean_text,
"分词结果": valid_words,
"有效词数": len(valid_words)
}
processed_corpus.append(processed_data)
# 每处理1000行,打印一次进度
if line_num % 1000 == 0:
print(f"已处理{line_num}行语料")
except Exception as e:
print(f" 处理第 {line_num} 行失败,错误原因:{e}")
continue
return processed_corpus
# ---------------------- 主程序:流式读取 + 结果保存 ----------------------
# if __name__ == '__main__':
# print(" 开始流式读取大JSON语料文件...")
# processed_result = stream_read_big_json(BIG_JSON_FILE)
# # 把处理后的结果,写入到新的JSON文件里
# with open("C:\\Users\\hp\\Desktop\\processed_corpus.json", 'w', encoding="utf-8") as f:
# json.dump(processed_result, f, ensure_ascii=False, indent=4)
#
# # 打印最终结果
# print(f"\n 大文件处理完成!")
# print(f"总处理行数:{len(processed_result)}")
# print(f"处理后的结果已保存到:processed_corpus.json")
# 进阶用法 3:JSON 嵌套数据的精准提取
# ---------------------- 模拟大模型API返回的复杂嵌套JSON结果 ----------------------
api_response_json = """
{
"id": "chatcmpl-20241231-001",
"object": "chat.completion",
"created": 1735689600,
"model": "ep-20240520182611-2jvzk",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "学习NLP自然语言处理,建议从以下几个步骤开始:1. 先掌握Python基础语法;2. 学习文本预处理;3. 学习核心NLP任务;4. 学习大模型API调用;5. 学习RAG检索增强生成技术。",
"refusal": null
},
"finish_reason": "stop",
"stop_reason": null
}
],
"usage": {
"prompt_tokens": 50,
"completion_tokens": 150,
"total_tokens": 200
},
"system_fingerprint": "fp_20241231",
"refs": ["NLP基础", "大模型API", "RAG"]
}
"""
# ---------------------- 从嵌套JSON里精准提取核心数据 ----------------------
# 把JSON字符串转换成Python字典
api_response = json.loads(api_response_json)
# 1. 提取第一层的基础数据
chat_id = api_response.get("id", "未知ID")
model_name = api_response.get("model", "未知模型")
create_time = api_response.get("created", 0)
print("【第一层基础数据】:")
print(f"对话ID:{chat_id}")
print(f"模型名称:{model_name}")
print(f"创建时间戳:{create_time}")
print("-"*50)
# 2. 提取第二层的Token消耗数据(嵌套对象)
usage_data = api_response.get("usage", {})
prompt_tokens = usage_data.get("prompt_tokens", 0)
completion_tokens = usage_data.get("completion_tokens", 0)
total_tokens = usage_data.get("total_tokens", 0)
print("【第二层Token消耗数据】:")
print(f"输入Token数:{prompt_tokens}")
print(f"输出Token数:{completion_tokens}")
print(f"总消耗Token数:{total_tokens}")
print("-"*50)
# 3. 提取第三层的AI回答内容(嵌套数组+嵌套对象)
choices_data = api_response.get("choices", [])
if len(choices_data) > 0:
first_choice = choices_data[0]
message_data = first_choice.get("message", {})
ai_answer = message_data.get("content", "无人回答")
finish_reason = first_choice.get("finish_reason","未知原因")
print("【第三层AI回答核心数据】:")
print(f"AI回答内容:{ai_answer}")
print(f"对话结束原因:{finish_reason}")
print("-" * 50)
# 4. 提取数组里的所有引用标签
refs_list = api_response.get('refs', [])
print("【第四层引用标签数据】:")
print(f"所有引用标签:{refs_list}")
for i, ref in enumerate(refs_list):
print(f"标签{i+1}:{ref}")
# 进阶用法 4:JSON 文件读取的格式校验与异常处理
# ---------------------- 核心配置 ----------------------
JSON_FILE_PATH = '/mnt/chat_history.json'
# 业务要求的JSON必须包含的键
REQUIRED_KEYS = ['对话ID', '用户问题', 'AI回答', '是否完成']
# ---------------------- 企业级JSON文件读取 + 格式校验 + 异常处理 ----------------------
def safe_read_json_file(file_path, required_keys = None):
"""
安全读取JSON文件,做完整的异常处理和格式校验
:param file_path: JSON文件路径
:param required_keys: 业务要求的必须包含的键列表
:return: 读取成功返回JSON数据,读取失败返回None
"""
# 1. 先校验文件是否存在
if not os.path.exists(file_path):
print(f" 读取失败:文件 {file_path} 不存在")
return None
# 2. 校验是否是文件(不是文件夹)
if not os.path.isfile(file_path):
print(f" 读取失败:{file_path} 不是一个文件")
return None
# 3. 校验是否有读取权限
if not os.access(file_path, os.R_OK):
print(f" 读取失败:没有读取文件 {file_path} 的权限")
return None
# 4. 读取文件并解析JSON,捕获所有异常
try:
with open(file_path, 'r', encoding='utf-8') as f:
# 读取文件内容
file_content = f.read()
# 解析JSON
json_data = json.loads(file_content)
except json.JSONDecodeError as e:
print(f" 读取失败:JSON格式错误,错误原因:{e}")
return None
except UnicodeDecodeError as e:
print(f" 读取失败:JSON格式错误,错误原因:{e}")
return None
except Exception as e:
print(f" 读取失败:未知错误,错误原因:{e}")
return None
# 5. 业务格式校验:检查是否包含必须的键
if required_keys:
# 如果JSON是数组,遍历每个元素校验
if isinstance(json_data,list):
for i, item in enumerate(json_data):
if not isinstance(item, dict):
print(f" 格式警告:第{i + 1}个元素不是字典格式")
continue
# 检查是否包含所有必须的键
missing_keys = [key for key in required_keys if key not in item]
if missing_keys:
print(f" 格式警告:第{i + 1}个元素缺少必须的键:{missing_keys}")
elif isinstance(json_data, dict):
missing_keys = [key for key in required_keys if key not in json_data]
if missing_keys:
print(f" 格式警告:JSON对象缺少必须的键:{missing_keys}")
# 6. 所有校验通过,返回JSON数据
print(f" 成功读取JSON文件:{file_path}")
return json_data
# 安全读取JSON文件,同时做业务格式校验
chat_data = safe_read_json_file(JSON_FILE_PATH, REQUIRED_KEYS)
# 读取成功,做后续处理
if chat_data:
print(f"\n 读取结果统计:")
if isinstance(chat_data, list):
print(f"总对话轮数:{len(chat_data)}")
# 统计已完成的对话
completed_chats = [chat for chat in chat_data if isinstance(chat, dict) and chat.get('是否完成', False)]
print(f"已完成对话数:{len(completed_chats)}")
print(f"对话完成率:{round(len(completed_chats) / len(chat_data) * 100, 2)}%")
""" 核心知识点 2:JSON 文件写入进阶用法 """
# 进阶用法 1:JSON 文件增量写入
import time
# ---------------------- 核心配置 ----------------------
# 对话历史JSON文件路径
CHAT_HISTORY_FILE = '/mnt/user_chat_history.jsonl'
# ---------------------- 对话历史增量写入函数 ----------------------
def append_chat_to_history(chat_data, file_path):
"""
把新的对话数据,增量写入到对话历史JSON文件里(行级JSON格式)
:param chat_data: 新的对话数据(字典格式)
:param file_path: 对话历史文件路径
:return: 写入成功返回True,失败返回False
"""
# 校验对话数据是否是字典格式
if not isinstance(chat_data, dict):
print(" 写入失败:对话数据必须是字典格式")
return False
# 把对话数据转换成JSON字符串,一行一个JSON对象
chat_json_str = json.dumps(chat_data, ensure_ascii=False) + '\n'
try:
# 用'a'模式打开文件,代表追加写入,不会覆盖原来的内容
with open(file_path, 'a', encoding='utf-8') as f:
# 把新的对话JSON字符串,写入到文件末尾
f.write(chat_json_str)
print(f" 成功把新对话写入到历史文件:{file_path}")
return True
except Exception as e:
print(f" 写入失败:{e}")
return False
# ---------------------- 主程序:模拟对话系统的增量写入 ----------------------
if __name__ == "__main__":
print("模拟大模型对话系统,增量写入对话历史...")
# 模拟3轮对话,每轮对话都增量写入到文件里
for i in range(1, 4):
# 模拟新的对话数据
new_chat = {
"对话ID": f"chat_20241231_{i:02d}",
"用户ID": "user_001",
"用户问题": f"我想学习NLP的第{i}个核心知识点",
"AI回答": f"这是NLP第{i}个核心知识点的详细讲解...",
"对话时间": time.strftime("%Y-%m-%d %H:%M:%S"),
"是否完成": True,
"消耗Token": 100 + i * 50
}
# 增量写入到对话历史文件里
append_chat_to_history(new_chat, CHAT_HISTORY_FILE)
# 模拟对话间隔
time.sleep(0.5)
print(f"\n 3轮对话全部写入完成!")
print(f"对话历史已保存到:{CHAT_HISTORY_FILE}")