搞懂你代码里的 os 和 json —— 从记忆系统的真实调用讲起
0. 先记住一句话
os= 和"操作系统 / 文件路径"打交道的工具箱。你用它定位文件在哪、拼出路径。json= 把 Python 的dict/list这类数据,变成字符串(存起来) 或 从字符串还原回来(读出来) 的工具。
你记忆系统里它们的关系:os 负责"把库文件放在哪个绝对位置",json 负责"把要存的数据变成能写进文件/数据库的文本"。两个配合,记忆才能"存得下、读得回"。
一、os.path:和路径打交道
你的 paths.py 第一行就是它:
| |
下面把这一行拆成三块讲。
1.1 __file__ —— “我这个文件自己叫啥、在哪”
每个 .py 文件运行时,Python 都会给它一个隐藏变量 __file__,内容是这个脚本的路径。
- 如果你在
C:\x\memory\里跑python paths.py,那__file__大致就是C:\x\memory\paths.py。 - 但有时候它可能是相对路径(取决于你怎么启动),所以不能裸用。
1.2 os.path.abspath(__file__) —— 变成"从盘符算起的绝对路径"
| |
作用:无论你从哪个目录启动程序,都把它矫正成完整的绝对路径。这样后面算出来的位置就不会随"当前目录(cwd)“漂移——这正是你记忆库"重启后还在原地"的关键。
1.3 os.path.dirname(...) —— 只拿走"目录"部分
| |
它把路径最后一段(文件名)砍掉,只留"文件夹”。于是:
| |
记忆里的作用:所有库(Chroma 文件夹、SQLite 文件)都建在 BASE 旁边,换目录运行也指向同一处,不会"找不到记忆"。
1.4 os.path.join(a, b) —— 安全地拼路径(别手写斜杠!)
| |
为什么不用 BASE + "/mem_store"?因为 Windows 用 \、Linux/Mac 用 /,手写斜杠在不同系统会出错。os.path.join 自动用当前系统的正确分隔符,跨平台安全。
💡 你项目里所有的落盘路径都该用
os.path.join拼,不要字符串硬拼。
1.5 os.path.exists(path) —— “这个路径在不在?”
来自你 local_store 示意里:
| |
| |
作用:第一次运行时 facts.json 还没建,os.path.exists 返回 False,就直接返回空字典 {},避免去读一个不存在的文件而报错。
二、json:把数据变成"能存起来的文本"
SQLite 的字段是文本,文件也想存结构化的 Python 对象(dict / list)。但文本只能存字符串,不能直接塞 dict。json 就是干这个转换的。
你的 profile_store.py:
| |
local_store 示意:
| |
2.1 json.dumps(obj) —— Python 对象 → JSON 字符串
| |
在记忆里的作用:ProfileStore.set_profile(k, v) 要把用户的画像 v(通常是 dict)写进 SQLite。但 SQLite 字段是文本,所以先用 json.dumps(v) 把它变成字符串,再存进去。
2.2 json.loads(s) —— JSON 字符串 → Python 对象
| |
在记忆里的作用:get_profile(k) 从 SQLite 读出来的是字符串(row[0]),用 json.loads(row[0]) 还原成原来的 dict,调用方才能当对象用。
2.3 json.dump(obj, f) / json.load(f) —— 直接读写整个文件
和上面那对很像,但这是直接操作文件对象:
| |
| 方法 | 吃进来的是 | 吐出去的是 | 记忆里谁用 |
|---|---|---|---|
json.dumps(obj) | Python 对象 | 字符串 | profile_store 写 SQLite 前 |
json.loads(s) | 字符串 | Python 对象 | profile_store 读 SQLite 后 |
json.dump(obj, f) | 对象 + 文件对象 | 无(写进文件) | local_store 写 facts.json |
json.load(f) | 文件对象 | Python 对象 | local_store 读 facts.json |
记法:带
s的那对(dumps/loads)处理"字符串";不带s的那对(dump/load)处理"文件"。
2.4 两个关键参数(你代码里已经用上了)
| |
ensure_ascii=False:默认True时,中文会被转成\u4e2d\u6587这种乱码。False才能正常显示"用户喜欢 DeepSeek"。存中文必加。indent=2:让 JSON 文件带缩进、换行,人眼可读。不加就是一整行挤在一起。
三、把 os + json 串起来看你的记忆系统
整条链路其实就三步:
os定位保险柜paths.py用os.path.dirname(os.path.abspath(__file__))+os.path.join算出MEM_STORE/PROFILE_DB/FACTS_JSON三个绝对路径。json把数据打包- 存用户画像:
json.dumps(v)把 dict 变字符串 → 写进 SQLite(PROFILE_DB)。 - 存简单事实:
json.dump(d, f, ensure_ascii=False, indent=2)直接写facts.json。
- 存用户画像:
json再把数据拆包- 读画像:
json.loads(row[0])把 SQLite 里的字符串还原成 dict。 - 读事实:
json.load(f)直接读回facts.json,并用os.path.exists判断文件是否存在。
- 读画像:
一句话:os 管"放在哪",json 管"怎么变成能存的文本"。
四、新手最常踩的坑(重点看)
坑 1:json.dumps 默认中文变乱码
| |
坑 2:loads 和 load 搞混
| |
坑 3:手写路径分隔符
| |
坑 4:文件打开不关(你代码里的隐藏小问题)
你现在的 json.load(open(path)) / open(path, "w") 没有关文件。学习期不影响,但规范写法用 with,出作用域自动关:
| |
五、速查卡片(复习直接看这)
| |