文件系统基础:理解文件系统、文件路径与Python路径表示
各位同学好,我是老张。今天咱们来聊聊文件系统操作中最基础、也最容易踩坑的部分——文件路径。说实话,我见过太多新手甚至工作一两年的工程师,在路径问题上翻车。我自己刚入行时也吃过不少亏,所以这部分内容,我建议你认真看完。
什么是文件系统?
文件系统,说白了就是操作系统用来组织和管理文件的一套规则。你想想看,你的硬盘那么大,文件那么多,如果没有一套规则,系统怎么知道文件存在哪?怎么快速找到它?
常见的文件系统有:
- Windows:NTFS、FAT32、exFAT
- macOS:APFS、HFS+
- Linux:ext4、XFS、Btrfs
不同的文件系统,底层实现不一样,但对外暴露的接口是相似的。我们做Python开发,不需要关心底层细节,只需要知道怎么通过路径找到文件就行。
绝对路径 vs 相对路径
这是今天最核心的概念。我直接说结论:绝对路径是从根目录开始的完整路径,相对路径是相对于当前工作目录的路径。
绝对路径
绝对路径就像你的家庭住址——从国家、省、市、区一直到门牌号,每一步都写清楚。比如:
- Windows:
C:\Users\zhangsan\projects\data\file.txt - Linux/macOS:
/home/zhangsan/projects/data/file.txt
绝对路径的好处是明确、唯一。不管你在哪个目录下执行代码,这个路径都指向同一个文件。
相对路径
相对路径就像你告诉朋友「往前走三个路口右转」——这个描述依赖于你们当前的位置。比如:
./data/file.txt—— 当前目录下的data文件夹里的file.txt../config/settings.json—— 上级目录的config文件夹里的settings.json../../logs/error.log—— 上上级目录的logs文件夹里的error.log
关键点: 相对路径中的 . 表示当前目录,.. 表示上级目录。这个规则在所有操作系统中通用。
我在项目中遇到过一个问题:同事写死了绝对路径 C:\Users\admin\project\data\file.txt,结果代码部署到服务器上直接报错。因为服务器上没有这个路径,用户名也不一样。从那以后,我团队里统一要求:项目代码中禁止使用绝对路径。
Python中的路径表示方法
Python里处理路径,主要有三种方式。我按推荐程度从低到高给你讲。
1. 原始字符串(Raw String)
在字符串前面加 r,告诉Python不要转义反斜杠:
# Windows路径,用原始字符串
path = r'C:\Users\zhangsan\data\file.txt'
print(path) # 输出:C:\Users\zhangsan\data\file.txt
嗯,这个方法能用,但不推荐。为什么?因为路径还是写死的,换个环境就废了。
2. 使用正斜杠(推荐)
Python在Windows上也支持正斜杠,所以你可以统一用正斜杠:
# 统一用正斜杠,跨平台兼容
path = 'C:/Users/zhangsan/data/file.txt'
print(path) # 输出:C:/Users/zhangsan/data/file.txt
这个方法比原始字符串好一点,但本质上还是硬编码路径。
3. 使用 os.path 模块(最推荐)
这才是专业做法。os.path 会根据当前操作系统自动选择正确的分隔符:
import os
# 拼接路径
path = os.path.join('data', 'subfolder', 'file.txt')
print(path) # Windows输出:data\subfolder\file.txt
# Linux/macOS输出:data/subfolder/file.txt
# 获取绝对路径
abs_path = os.path.abspath('file.txt')
print(abs_path) # 输出完整绝对路径
# 获取当前工作目录
cwd = os.getcwd()
print(cwd) # 输出当前目录
# 判断路径是否存在
exists = os.path.exists('data/file.txt')
print(exists) # True 或 False
# 分离文件名和目录
dirname = os.path.dirname('/home/user/data/file.txt')
basename = os.path.basename('/home/user/data/file.txt')
print(dirname) # /home/user/data
print(basename) # file.txt
path = 'data/' + filename。在Windows上跑得好好的,部署到Linux服务器上就报错。因为Linux路径分隔符是正斜杠,但如果你拼接时用了反斜杠,就全乱了。所以,永远用 os.path.join 来拼接路径。
当前工作目录(CWD)
这个概念太重要了,我单独拿出来讲。当前工作目录就是你的Python程序「当前所在的位置」。当你使用相对路径时,Python会从这个位置开始找文件。
举个例子:
import os
# 打印当前工作目录
print(os.getcwd()) # 比如输出:/home/user/project
# 使用相对路径
with open('data/file.txt', 'r') as f:
content = f.read()
# 实际打开的是:/home/user/project/data/file.txt
为什么会这样?因为相对路径 data/file.txt 是相对于当前工作目录 /home/user/project 的。
你想想看,如果你在终端里执行 python script.py,当前工作目录就是终端所在的目录。如果你在IDE里运行,当前工作目录通常是项目根目录。这个差异,经常导致「在我电脑上能跑,在你电脑上就跑不了」的问题。
__file__ 获取脚本所在目录,然后基于它构建路径。这样不管从哪里执行,路径都是正确的。
import os
# 获取当前脚本所在目录
script_dir = os.path.dirname(os.path.abspath(__file__))
# 切换到脚本目录
os.chdir(script_dir)
# 现在所有相对路径都基于脚本目录了
with open('data/file.txt', 'r') as f:
content = f.read()
路径操作实战
最后,我给你一个完整的实战示例。假设你的项目结构是这样的:
project/
├── scripts/
│ └── process.py
├── data/
│ └── input.csv
└── output/
└── result.txt
在 process.py 中,你想读取 data/input.csv,写入 output/result.txt。正确的做法是:
import os
# 获取当前脚本所在目录
script_dir = os.path.dirname(os.path.abspath(__file__))
# 获取项目根目录(scripts的上级目录)
project_dir = os.path.dirname(script_dir)
# 构建数据文件路径
input_path = os.path.join(project_dir, 'data', 'input.csv')
output_path = os.path.join(project_dir, 'output', 'result.txt')
# 检查路径是否存在
if not os.path.exists(input_path):
print(f'错误:找不到输入文件 {input_path}')
exit(1)
# 确保输出目录存在
output_dir = os.path.dirname(output_path)
os.makedirs(output_dir, exist_ok=True)
# 读取和写入
with open(input_path, 'r') as f_in:
data = f_in.read()
with open(output_path, 'w') as f_out:
f_out.write(data)
print('处理完成!')
这段代码有几个关键点:
- 用
__file__获取脚本路径,不依赖当前工作目录 - 用
os.path.join拼接路径,跨平台兼容 - 用
os.path.exists检查文件是否存在 - 用
os.makedirs自动创建目录
说实话,这套写法我用了快十年,从来没出过问题。你直接拿去用就行。
总结
今天的内容就这些。核心就三点:
- 绝对路径 vs 相对路径:项目里永远用相对路径
- Python路径操作:用
os.path模块,别自己拼字符串 - 当前工作目录:用
__file__定位脚本位置,别依赖CWD
下一章我们讲文件读写操作,到时候会用到今天学的路径知识。你先把这些基础打牢,后面就顺了。