pathlib 在处理**符号链接(symlink)**时确实有不少“暗坑”,尤其是涉及 .resolve()、文件操作、权限、跨平台行为时,很容易踩异常或得到和预期不一致的结果。
下面把常见异常 + 触发场景 + 正确用法给你讲透。
一、最常见异常一览
1️⃣ FileNotFoundError(断链)
from pathlib import Path
p = Path("broken_link")
p.resolve()
? 如果符号链接指向的目标不存在:
❗抛出 FileNotFoundError
✅ 解决方式
p.resolve(strict=False)
? 不检查目标是否存在,返回“理论路径”
二、循环符号链接(死循环)
2️⃣ RuntimeError: Symlink loop
a -> b
b -> a
Path("a").resolve()
? 会抛:
❗RuntimeError: Symlink loop detected
✅ 解决方式
p.resolve(strict=False)
或者自己限制深度:
import os
os.path.realpath("a") # 有时更宽容
三、权限问题
3️⃣ PermissionError
Path("/root/secret_link").resolve()
? 如果中间路径没有权限:
❗抛 PermissionError
✅ 解决建议
提前判断权限
或 try/except 包裹
try:
p.resolve()
except PermissionError:
...
四、.exists() 的坑(非常容易误判)
p = Path("link")
p.exists()
? 行为:
情况 exists()
正常链接 True
断链 ❌ False
? 这就坑了:
❗你无法区分“文件不存在”和“符号链接坏了”
✅ 正确判断方式
p.is_symlink()
p.exists()
组合判断:
if p.is_symlink() and not p.exists():
print("断链")
五、.unlink() 删除符号链接的误解
p.unlink()
? 删除的是:
✅ 符号链接本身
❌ 不会删除目标文件
但如果你先 .resolve() 再删:
p.resolve().unlink()
? 就变成:
❗删除真实文件(危险)
六、.resolve() vs .absolute()
很多人用错?
❗区别:
p.resolve()
? 解析符号链接 → 得到真实路径
p.absolute()
? 只是变绝对路径,不解析 symlink
举例:
link -> /real/file.txt
Path("link").absolute()
# /当前目录/link
Path("link").resolve()
# /real/file.txt
七、跨平台问题(Windows 特别坑)
⚠️ Windows 下:
创建 symlink 需要管理员权限(或开发者模式)
有两种:
文件链接
目录链接
可能异常:
OSError: symbolic link privilege not held
✅ 建议
import os
os.symlink(src, dst, target_is_directory=True)
八、.readlink() 的坑
p.readlink()
? 返回的是:
❗原始路径(可能是相对路径)
示例
link -> ../file.txt
p.readlink()
# "../file.txt"
? 不是绝对路径!
✅ 正确做法
(p.parent / p.readlink()).resolve()
九、.samefile() 可能抛异常
p1.samefile(p2)
? 如果路径不存在:
❗抛 FileNotFoundError
十、最佳实践(强烈建议)
✅ 安全处理模板
from pathlib import Path
def safe_resolve(p: Path):
try:
return p.resolve()
except FileNotFoundError:
return p.resolve(strict=False)
except RuntimeError:
print("检测到循环符号链接")
return None
except PermissionError:
print("权限不足")
return None
✅ 判断路径类型(推荐组合)
if p.is_symlink():
if not p.exists():
print("断链")
else:
print("正常符号链接")
elif p.exists():
print("普通文件")
else:
print("不存在")
十一、一句话总结
? pathlib + symlink 核心坑:
❗.resolve() 会触发异常
❗.exists() 会隐藏断链
❗.unlink() + .resolve() 可能误删真实文件
如果你是做自动化(你之前在搞 Selenium)
我给你一个实用建议?
? 下载目录 / 配置目录 / 浏览器缓存
经常会遇到 symlink(尤其 Linux)
建议你:
永远用 resolve(strict=False)
删除前先 is_symlink()
不要链式 .resolve().unlink()