Python 基础课:文件操作、异常处理与日志
学习目标
今天结束后,你能够:
- 使用 open() 读写文本文件
- 处理文件路径(相对路径、绝对路径)
- 使用 with 语句自动管理文件资源
- 捕获和处理异常(try-except)
- 记录程序日志(logging 模块)
- 读写 JSON 文件存储数据
- 处理 CSV 文件
- 构建对话记录保存系统
文件读取
文件操作是数据持久化的基础。AI 应用中需要读取 prompt 模板、知识库文档、配置文件等。
为什么需要文件操作
程序运行时的数据存储在内存中,程序关闭后数据就消失了。文件操作让数据可以:
- 永久保存
- 跨程序共享
- 批量处理
基本文件读取
open() 函数
# 打开文件
file = open("example.txt", "r", encoding="utf-8")
# r: 读取模式
# encoding: 指定编码,中文文件必须指定 utf-8
# 读取内容
content = file.read()
print(content)
# 关闭文件(重要!)
file.close()
文件读取模式:
"r"- 只读(默认)"w"- 写入(覆盖)"a"- 追加"r+"- 读写
with 语句(推荐)
with 语句会自动关闭文件,即使发生错误也能正确关闭。
with open("example.txt", "r", encoding="utf-8") as file:
content = file.read()
print(content)
# 离开 with 块后,文件自动关闭
读取方法
read() - 读取全部内容
with open("prompt.txt", "r", encoding="utf-8") as f:
content = f.read()
print(content)
readline() - 逐行读取
with open("prompt.txt", "r", encoding="utf-8") as f:
line1 = f.readline() # 读取第一行
line2 = f.readline() # 读取第二行
print(line1)
print(line2)
readlines() - 读取所有行到列表
with open("prompts.txt", "r", encoding="utf-8") as f:
lines = f.readlines() # 返回列表,每个元素是一行
for line in lines:
print(line.strip()) # strip() 去除行尾换行符
遍历文件对象
with open("prompts.txt", "r", encoding="utf-8") as f:
for line in f: # 直接遍历文件对象
print(line.strip())
AI 场景示例
# 读取 prompt 模板
with open("system_prompt.txt", "r", encoding="utf-8") as f:
system_prompt = f.read()
print("=== 系统 Prompt ===")
print(system_prompt)
# 读取多个 prompt 模板
prompts = {}
template_files = ["coder.txt", "translator.txt", "helper.txt"]
for filename in template_files:
role = filename.replace(".txt", "")
with open(f"prompts/{filename}", "r", encoding="utf-8") as f:
prompts[role] = f.read()
print(prompts["coder"])
课堂练习
读取知识库文档
创建一个 knowledge.txt 文件,内容如下:
Python 是一门编程语言
适合 AI 开发
语法简洁易学
读取并打印每一行。
参考答案:
with open("knowledge.txt", "r", encoding="utf-8") as f:
for line in f:
print(line.strip())
输出:
Python 是一门编程语言
适合 AI 开发
语法简洁易学
文件写入
写入模式
“w” - 覆盖写入
with open("output.txt", "w", encoding="utf-8") as f:
f.write("Hello, Python!\n")
f.write("这是第二行\n")
注意:"w" 模式会覆盖原文件内容!
“a” - 追加写入
with open("log.txt", "a", encoding="utf-8") as f:
f.write("新日志记录\n")
写入方法
write() - 写入字符串
with open("output.txt", "w", encoding="utf-8") as f:
f.write("第一行\n")
f.write("第二行\n")
writelines() - 写入列表
lines = ["第一行\n", "第二行\n", "第三行\n"]
with open("output.txt", "w", encoding="utf-8") as f:
f.writelines(lines)
AI 场景示例
# 保存对话记录
messages = [
{"role": "user", "content": "你好"},
{"role": "assistant", "content": "你好!有什么可以帮你?"}
]
with open("chat_history.txt", "w", encoding="utf-8") as f:
for msg in messages:
line = f"[{msg['role']}] {msg['content']}\n"
f.write(line)
print("对话记录已保存")
输出文件内容:
[user] 你好
[assistant] 你好!有什么可以帮你?
课堂练习
生成 Prompt 文件
根据用户输入生成 prompt 并保存到文件。
参考答案:
role = input("请输入角色: ")
task = input("请输入任务: ")
prompt = f"""你是一个{role}。
任务:{task}
请按照要求完成任务。
"""
with open("generated_prompt.txt", "w", encoding="utf-8") as f:
f.write(prompt)
print("Prompt 已保存到 generated_prompt.txt")
文件路径
相对路径 vs 绝对路径
相对路径: 相对于当前工作目录
# 当前目录下的文件
"data.txt"
# 当前目录下的子目录
"data/chat.txt"
# 上级目录
"../config.txt"
绝对路径: 从根目录开始的完整路径
# Windows
"C:/Users/username/project/data.txt"
# macOS/Linux
"/Users/username/project/data.txt"
os.path 模块
os.path 提供了跨平台的路径操作函数。
import os
# 拼接路径(自动处理斜杠)
path = os.path.join("data", "prompts", "system.txt")
print(path) # Windows: data\prompts\system.txt
# macOS: data/prompts/system.txt
# 检查文件是否存在
if os.path.exists("data.txt"):
print("文件存在")
else:
print("文件不存在")
# 检查是否是文件
print(os.path.isfile("data.txt"))
# 检查是否是目录
print(os.path.isdir("data"))
# 获取文件名
filename = os.path.basename("/path/to/file.txt")
print(filename) # file.txt
# 获取目录名
dirname = os.path.dirname("/path/to/file.txt")
print(dirname) # /path/to
# 获取当前工作目录
cwd = os.getcwd()
print(cwd)
# 创建目录
os.makedirs("data/logs", exist_ok=True) # exist_ok=True 表示目录存在时不报错
pathlib 模块(推荐)
pathlib 是更现代的路径操作方式,面向对象。
from pathlib import Path
# 创建路径对象
path = Path("data/prompts/system.txt")
# 检查是否存在
if path.exists():
print("文件存在")
# 读取文件
content = path.read_text(encoding="utf-8")
# 写入文件
path.write_text("新内容", encoding="utf-8")
# 获取父目录
parent = path.parent
print(parent) # data/prompts
# 获取文件名
print(path.name) # system.txt
# 获取后缀
print(path.suffix) # .txt
# 遍历目录
data_dir = Path("data")
for file in data_dir.glob("*.txt"): # 所有 .txt 文件
print(file)
AI 场景示例
from pathlib import Path
# 组织项目文件结构
project_dir = Path("my_ai_project")
data_dir = project_dir / "data"
logs_dir = project_dir / "logs"
# 创建目录
data_dir.mkdir(parents=True, exist_ok=True)
logs_dir.mkdir(parents=True, exist_ok=True)
# 保存对话记录
chat_file = data_dir / "chat_20240611.txt"
with open(chat_file, "w", encoding="utf-8") as f:
f.write("对话记录...\n")
print(f"对话记录已保存到: {chat_file}")
JSON 文件处理
JSON 是 AI 开发中最常用的数据格式,用于存储配置、消息、API 响应等。
为什么使用 JSON
- 人类可读
- 跨语言通用
- 支持复杂数据结构(嵌套字典、列表)
- AI API 的标准格式
JSON 基础操作
写入 JSON 文件
import json
# Python 数据结构
data = {
"model": "gpt-4",
"temperature": 0.7,
"messages": [
{"role": "user", "content": "你好"},
{"role": "assistant", "content": "你好!"}
]
}
# 保存到文件
with open("config.json", "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
# ensure_ascii=False: 保存中文而不是 \uXXXX
# indent=2: 格式化输出,方便阅读
print("已保存到 config.json")
生成的 config.json:
{
"model": "gpt-4",
"temperature": 0.7,
"messages": [
{
"role": "user",
"content": "你好"
},
{
"role": "assistant",
"content": "你好!"
}
]
}
读取 JSON 文件
import json
with open("config.json", "r", encoding="utf-8") as f:
data = json.load(f) # 解析 JSON 为 Python 对象
print(data["model"]) # gpt-4
print(data["messages"][0]["content"]) # 你好
AI 场景示例
import json
from datetime import datetime
# 保存对话记录(带时间戳)
def save_chat_history(messages, filename="chat_history.json"):
"""保存对话记录到 JSON 文件"""
chat_data = {
"timestamp": datetime.now().isoformat(),
"messages": messages
}
with open(filename, "w", encoding="utf-8") as f:
json.dump(chat_data, f, ensure_ascii=False, indent=2)
print(f"对话记录已保存: {filename}")
# 加载对话记录
def load_chat_history(filename="chat_history.json"):
"""从 JSON 文件加载对话记录"""
try:
with open(filename, "r", encoding="utf-8") as f:
data = json.load(f)
return data["messages"]
except FileNotFoundError:
print("文件不存在,返回空列表")
return []
# 使用
messages = [
{"role": "system", "content": "你是助手"},
{"role": "user", "content": "你好"},
{"role": "assistant", "content": "你好!"}
]
save_chat_history(messages)
loaded = load_chat_history()
print(f"加载了 {len(loaded)} 条消息")
课堂练习
配置文件管理
创建一个配置管理系统,保存和读取 AI 模型配置。
参考答案:
import json
def save_config(config, filename="config.json"):
"""保存配置"""
with open(filename, "w", encoding="utf-8") as f:
json.dump(config, f, ensure_ascii=False, indent=2)
def load_config(filename="config.json"):
"""加载配置"""
with open(filename, "r", encoding="utf-8") as f:
return json.load(f)
# 测试
config = {
"model": "gpt-4",
"temperature": 0.7,
"max_tokens": 2000,
"system_prompt": "你是一个Python助手"
}
save_config(config)
print("配置已保存")
loaded_config = load_config()
print(f"模型: {loaded_config['model']}")
print(f"温度: {loaded_config['temperature']}")
异常处理
程序运行时可能遇到各种错误:文件不存在、网络断开、数据格式错误等。异常处理让程序更健壮。
为什么需要异常处理
没有异常处理时,一个错误会导致程序崩溃:
# 文件不存在,程序直接崩溃
with open("not_exists.txt", "r") as f:
content = f.read()
# FileNotFoundError: [Errno 2] No such file or directory: 'not_exists.txt'
有异常处理时,可以优雅地处理错误:
try:
with open("not_exists.txt", "r") as f:
content = f.read()
except FileNotFoundError:
print("文件不存在,使用默认配置")
content = "默认内容"
try-except 基础
基本语法:
try:
# 可能出错的代码
result = 10 / 0
except ZeroDivisionError:
# 处理特定错误
print("不能除以零")
捕获多种异常:
try:
value = int("abc")
except ValueError:
print("值错误")
except TypeError:
print("类型错误")
捕获所有异常:
try:
# 危险操作
risky_operation()
except Exception as e:
print(f"发生错误: {e}")
try-except-else-finally
完整的异常处理结构:
try:
# 可能出错的代码
with open("data.txt", "r") as f:
data = f.read()
except FileNotFoundError:
# 处理文件不存在
print("文件不存在")
data = ""
except Exception as e:
# 处理其他错误
print(f"未知错误: {e}")
data = ""
else:
# 没有异常时执行
print("文件读取成功")
finally:
# 无论是否异常都执行(常用于清理资源)
print("操作完成")
AI 场景示例
import json
def load_config_safe(filename="config.json"):
"""安全加载配置文件"""
try:
with open(filename, "r", encoding="utf-8") as f:
config = json.load(f)
print(f"配置加载成功: {filename}")
return config
except FileNotFoundError:
print(f"配置文件不存在: {filename},使用默认配置")
return {
"model": "gpt-3.5-turbo",
"temperature": 0.7
}
except json.JSONDecodeError as e:
print(f"JSON 格式错误: {e}")
return {}
except Exception as e:
print(f"未知错误: {e}")
return {}
# 使用
config = load_config_safe("config.json")
print(f"模型: {config.get('model', '未设置')}")
课堂练习
健壮的文件读取
编写函数,安全地读取文件,如果失败返回默认值。
参考答案:
def read_file_safe(filename, default=""):
"""安全读取文件"""
try:
with open(filename, "r", encoding="utf-8") as f:
return f.read()
except FileNotFoundError:
print(f"文件不存在: {filename}")
return default
except UnicodeDecodeError:
print(f"编码错误: {filename}")
return default
except Exception as e:
print(f"读取失败: {e}")
return default
# 测试
content = read_file_safe("prompt.txt", "默认 Prompt")
print(content)
日志记录
print() 只能输出到控制台,日志可以保存到文件,方便追踪问题。
为什么使用日志
- 记录程序运行状态
- 调试问题
- 监控错误
- 审计操作
logging 模块基础
基本配置:
import logging
# 配置日志
logging.basicConfig(
level=logging.INFO, # 日志级别
format='%(asctime)s - %(levelname)s - %(message)s', # 日志格式
filename='app.log', # 输出到文件
encoding='utf-8'
)
# 记录日志
logging.debug("调试信息")
logging.info("程序启动")
logging.warning("警告:配置缺失")
logging.error("错误:文件不存在")
logging.critical("严重错误:系统崩溃")
日志级别
从低到高:
- DEBUG:详细调试信息
- INFO:一般信息
- WARNING:警告
- ERROR:错误
- CRITICAL:严重错误
只有大于等于设定级别的日志才会被记录。
同时输出到控制台和文件
import logging
# 创建 logger
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
# 文件处理器
file_handler = logging.FileHandler('app.log', encoding='utf-8')
file_handler.setLevel(logging.INFO)
# 控制台处理器
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.DEBUG)
# 格式化
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
file_handler.setFormatter(formatter)
console_handler.setFormatter(formatter)
# 添加处理器
logger.addHandler(file_handler)
logger.addHandler(console_handler)
# 使用
logger.info("程序启动")
logger.warning("配置缺失")
logger.error("发生错误")
AI 场景示例
import logging
import json
# 配置日志
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
filename='ai_app.log',
encoding='utf-8'
)
def call_ai_api(prompt):
"""调用 AI API(模拟)"""
logging.info(f"调用 API,prompt 长度: {len(prompt)}")
try:
# 模拟 API 调用
if len(prompt) == 0:
raise ValueError("Prompt 不能为空")
# 模拟响应
response = "这是 AI 的回复"
logging.info("API 调用成功")
return response
except ValueError as e:
logging.error(f"参数错误: {e}")
return None
except Exception as e:
logging.critical(f"API 调用失败: {e}")
return None
# 使用
result = call_ai_api("你好")
if result:
print(f"回复: {result}")
else:
print("调用失败")
课堂练习
带日志的文件操作
为文件读写操作添加日志记录。
参考答案:
import logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
filename='file_operations.log',
encoding='utf-8'
)
def save_data(filename, data):
"""保存数据并记录日志"""
try:
logging.info(f"开始保存数据到: {filename}")
with open(filename, "w", encoding="utf-8") as f:
f.write(data)
logging.info(f"数据保存成功: {filename}")
return True
except Exception as e:
logging.error(f"保存失败: {e}")
return False
# 测试
success = save_data("output.txt", "测试数据")
print(f"保存{'成功' if success else '失败'}")
CSV 文件处理
CSV 是常见的表格数据格式,常用于数据交换和批量处理。
csv 模块
读取 CSV:
import csv
# 读取 CSV 文件
with open("models.csv", "r", encoding="utf-8") as f:
reader = csv.reader(f)
# 跳过表头
header = next(reader)
print(f"表头: {header}")
# 读取数据
for row in reader:
print(row)
models.csv 内容:
model,price,max_tokens
gpt-3.5-turbo,0.002,4096
gpt-4,0.03,8192
claude-3,0.015,100000
使用 DictReader(推荐):
import csv
with open("models.csv", "r", encoding="utf-8") as f:
reader = csv.DictReader(f) # 自动解析表头
for row in reader:
print(f"模型: {row['model']}, 价格: {row['price']}")
输出:
模型: gpt-3.5-turbo, 价格: 0.002
模型: gpt-4, 价格: 0.03
模型: claude-3, 价格: 0.015
写入 CSV:
import csv
data = [
["model", "price", "max_tokens"],
["gpt-3.5-turbo", "0.002", "4096"],
["gpt-4", "0.03", "8192"]
]
with open("output.csv", "w", encoding="utf-8", newline='') as f:
writer = csv.writer(f)
writer.writerows(data)
print("CSV 文件已保存")
使用 DictWriter:
import csv
data = [
{"model": "gpt-3.5-turbo", "price": 0.002, "max_tokens": 4096},
{"model": "gpt-4", "price": 0.03, "max_tokens": 8192}
]
with open("output.csv", "w", encoding="utf-8", newline='') as f:
fieldnames = ["model", "price", "max_tokens"]
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader() # 写入表头
writer.writerows(data) # 写入数据
print("CSV 文件已保存")
AI 场景示例
import csv
from datetime import datetime
def log_api_call(model, tokens, cost, filename="api_log.csv"):
"""记录 API 调用到 CSV"""
# 检查文件是否存在
import os
file_exists = os.path.exists(filename)
with open(filename, "a", encoding="utf-8", newline='') as f:
fieldnames = ["timestamp", "model", "tokens", "cost"]
writer = csv.DictWriter(f, fieldnames=fieldnames)
# 如果文件不存在,写入表头
if not file_exists:
writer.writeheader()
# 写入数据
writer.writerow({
"timestamp": datetime.now().isoformat(),
"model": model,
"tokens": tokens,
"cost": cost
})
# 使用
log_api_call("gpt-4", 1500, 0.045)
log_api_call("gpt-3.5-turbo", 800, 0.0016)
print("API 调用已记录")
当天作业
对话记录管理系统
实现一个完整的对话记录管理系统,支持保存、加载、追加对话。
参考答案:
import json
from datetime import datetime
from pathlib import Path
class ChatManager:
"""对话管理器"""
def __init__(self, data_dir="chat_data"):
self.data_dir = Path(data_dir)
self.data_dir.mkdir(exist_ok=True)
def save_chat(self, messages, session_id=None):
"""保存对话"""
if session_id is None:
session_id = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = self.data_dir / f"chat_{session_id}.json"
data = {
"session_id": session_id,
"timestamp": datetime.now().isoformat(),
"messages": messages
}
with open(filename, "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
print(f"对话已保存: {filename}")
return session_id
def load_chat(self, session_id):
"""加载对话"""
filename = self.data_dir / f"chat_{session_id}.json"
try:
with open(filename, "r", encoding="utf-8") as f:
data = json.load(f)
return data["messages"]
except FileNotFoundError:
print(f"会话不存在: {session_id}")
return []
except json.JSONDecodeError:
print(f"文件格式错误: {filename}")
return []
def list_sessions(self):
"""列出所有会话"""
sessions = []
for file in self.data_dir.glob("chat_*.json"):
session_id = file.stem.replace("chat_", "")
sessions.append(session_id)
return sorted(sessions)
# 测试
manager = ChatManager()
# 保存对话
messages = [
{"role": "user", "content": "你好"},
{"role": "assistant", "content": "你好!"}
]
session_id = manager.save_chat(messages)
# 加载对话
loaded_messages = manager.load_chat(session_id)
print(f"加载了 {len(loaded_messages)} 条消息")
# 列出所有会话
sessions = manager.list_sessions()
print(f"共有 {len(sessions)} 个会话")
Prompt 模板管理器
创建一个 Prompt 模板管理系统,支持多个模板。
参考答案:
import json
from pathlib import Path
class PromptManager:
"""Prompt 模板管理器"""
def __init__(self, templates_file="prompt_templates.json"):
self.templates_file = Path(templates_file)
self.templates = self._load_templates()
def _load_templates(self):
"""加载模板"""
try:
with open(self.templates_file, "r", encoding="utf-8") as f:
return json.load(f)
except FileNotFoundError:
return {}
def _save_templates(self):
"""保存模板"""
with open(self.templates_file, "w", encoding="utf-8") as f:
json.dump(self.templates, f, ensure_ascii=False, indent=2)
def add_template(self, name, template):
"""添加模板"""
self.templates[name] = template
self._save_templates()
print(f"模板已添加: {name}")
def get_template(self, name):
"""获取模板"""
return self.templates.get(name, "")
def list_templates(self):
"""列出所有模板"""
return list(self.templates.keys())
def delete_template(self, name):
"""删除模板"""
if name in self.templates:
del self.templates[name]
self._save_templates()
print(f"模板已删除: {name}")
else:
print(f"模板不存在: {name}")
# 测试
manager = PromptManager()
# 添加模板
manager.add_template("coder", "你是一个专业的编程助手")
manager.add_template("translator", "你是一个专业的翻译助手")
# 列出模板
templates = manager.list_templates()
print(f"可用模板: {templates}")
# 使用模板
system_prompt = manager.get_template("coder")
print(f"系统 Prompt: {system_prompt}")
API 调用统计
记录 API 调用并生成统计报告。
参考答案:
import csv
import json
from datetime import datetime
from pathlib import Path
class APILogger:
"""API 调用日志记录器"""
def __init__(self, log_file="api_calls.csv"):
self.log_file = Path(log_file)
def log_call(self, model, input_tokens, output_tokens, cost):
"""记录一次 API 调用"""
file_exists = self.log_file.exists()
with open(self.log_file, "a", encoding="utf-8", newline='') as f:
fieldnames = ["timestamp", "model", "input_tokens",
"output_tokens", "total_tokens", "cost"]
writer = csv.DictWriter(f, fieldnames=fieldnames)
if not file_exists:
writer.writeheader()
writer.writerow({
"timestamp": datetime.now().isoformat(),
"model": model,
"input_tokens": input_tokens,
"output_tokens": output_tokens,
"total_tokens": input_tokens + output_tokens,
"cost": cost
})
def get_statistics(self):
"""生成统计报告"""
if not self.log_file.exists():
return {"total_calls": 0, "total_cost": 0}
total_calls = 0
total_cost = 0.0
total_tokens = 0
model_stats = {}
with open(self.log_file, "r", encoding="utf-8") as f:
reader = csv.DictReader(f)
for row in reader:
total_calls += 1
total_cost += float(row["cost"])
total_tokens += int(row["total_tokens"])
model = row["model"]
if model not in model_stats:
model_stats[model] = {"calls": 0, "cost": 0.0}
model_stats[model]["calls"] += 1
model_stats[model]["cost"] += float(row["cost"])
return {
"total_calls": total_calls,
"total_cost": total_cost,
"total_tokens": total_tokens,
"model_stats": model_stats
}
# 测试
logger = APILogger()
# 记录调用
logger.log_call("gpt-4", 1000, 500, 0.045)
logger.log_call("gpt-3.5-turbo", 800, 400, 0.0024)
logger.log_call("gpt-4", 1200, 600, 0.054)
# 查看统计
stats = logger.get_statistics()
print(f"总调用次数: {stats['total_calls']}")
print(f"总费用: ${stats['total_cost']:.4f}")
print(f"总 Token 数: {stats['total_tokens']}")
print("\n各模型统计:")
for model, data in stats["model_stats"].items():
print(f" {model}: {data['calls']} 次, ${data['cost']:.4f}")
输出:
总调用次数: 3
总费用: $0.1014
总 Token 数: 4500
各模型统计:
gpt-4: 2 次, $0.0990
gpt-3.5-turbo: 1 次, $0.0024
今日总结
核心知识点回顾
1. 文件操作
open()打开文件,模式:r/w/awith语句自动关闭文件- 读取:read(), readline(), readlines()
- 写入:write(), writelines()
2. 路径处理
- 相对路径 vs 绝对路径
- os.path:跨平台路径操作
- pathlib:面向对象的路径操作(推荐)
3. JSON 文件
- json.dump():保存到文件
- json.load():从文件加载
- ensure_ascii=False:保存中文
- indent:格式化输出
4. 异常处理
- try-except:捕获异常
- try-except-else-finally:完整结构
- 捕获特定异常类型
- Exception:捕获所有异常
5. 日志记录
- logging 模块
- 日志级别:DEBUG < INFO < WARNING < ERROR < CRITICAL
- basicConfig:简单配置
- Handler:输出到文件和控制台
6. CSV 文件
- csv.reader / csv.writer
- csv.DictReader / csv.DictWriter(推荐)
- newline=”:写入时避免空行
常见问题
Q:为什么要用 with 语句? A:自动关闭文件,即使发生异常也能正确关闭,避免资源泄漏。
Q:相对路径和绝对路径该用哪个? A:项目内部文件用相对路径,便于移植;外部文件或配置用绝对路径。
Q:JSON 和 CSV 该选哪个? A:复杂嵌套数据用 JSON;简单表格数据用 CSV;AI 消息和配置通常用 JSON。
Q:什么时候应该捕获异常? A:可能失败的 I/O 操作(文件、网络)、用户输入、外部 API 调用。
Q:日志和 print 有什么区别? A:print 只能输出到控制台;日志可以保存、分级、格式化,适合生产环境。
重点注意事项
-
文件编码:中文文件必须指定
encoding="utf-8" -
异常粒度:捕获具体异常而不是所有 Exception
# 好 try: f = open("file.txt") except FileNotFoundError: pass # 差 try: f = open("file.txt") except Exception: # 太宽泛 pass -
资源清理:使用 with 或 finally 确保资源释放
-
JSON 中文:
ensure_ascii=False避免中文变成 \uXXXX -
CSV 空行:写入时使用
newline=''避免空行