Python小酷库系列:玩转Python文件系统工具库(一)


Python的一大用途就是对文件系统进行各种操作,如文件批量改名、替换内容、遍历目录等等,掌握这些文件系统基本操作的常常是入门Python时的最大乐趣。尽管如此,很多教程往往将文件系统的操作作为示例中的甜点,而没有系统地去介绍这部分内容。所以本节开始我们讨论Python中的文件系统操作。

1、Python内置的文件系统操作工具

Python 标准库提供了多个内置模块来进行文件和目录操作。常用的主要有:

模块作用简介
os老式的文件系统接口,处理权限、低层访问等
pathlib现代的面向对象路径操作方式,跨平台、安全
shutil提供复制、移动、压缩等高级文件和目录操作
tempfile创建临时文件和目录
zipfile操作 .zip 压缩文件
fnmatchUnix 风格的文件名匹配(类似 shell 的 *.txt)

这里值得注意的是:在Python3.4之前,关于文件路径的操作功能主要被放在了os.path 模块中,而Python3.4推出了全新的pathlib库,它采用了面向对象的设计理念,将路径视为一个对象,并为此提供了丰富的属性和方法来进行各种操作。这种方式不仅代码更加简洁明了,也减少了错误的发生。
pathlib的类结构大体如下:

«abstract»
PurePath
+parts
+joinpath()
+match()
PurePosixPath
PureWindowsPath
Path
+exists()
+is_file()
+is_dir()
+mkdir()
+rmdir()
+read_text()
+write_text()
PosixPath
WindowsPath
类名用途
Path核心类,表示一个文件或目录路径(自动适配 OS)
PurePath不涉及文件系统的路径类(只做字符串处理)
PurePosixPathPOSIX 专用的纯路径
PureWindowsPathWindows 专用的纯路径
PosixPathPOSIX 实际路径类(Linux/macOS 使用)
WindowsPathWindows 实际路径类(Windows 使用)

2、路径与文件名操作

在开始讨论文件系统的操作前,我们必须对文件/目录的路径有一个基本的认识,我们知道在计算机中,文件 / 目录的路径用于指示文件或目录在文件系统中的具体位置,它就像是一份 “地图”,帮助操作系统和用户快速找到所需的文件或目录。

路径的结构

在文件系统中,一个完整的路径通常由以下几个部分组成:

路径结构示意(类 Unix 和 Windows 类似):

/home/user/docs/report.txt
│     │     │       └── 文件名(name)
│     │     └── 上级目录(parent)
│     └── 用户目录
└── 根目录(根路径)

对此pathlib将为此而生成一个Path对象,并进行如下解析:

组件pathlib 属性示例值
根路径.anchor‘/’(Linux), ‘C:\’(Windows)
父路径.parent‘home/user/docs’
文件名.name‘report.txt’
主干名.stem‘report’
扩展名.suffix‘.txt’
所有后缀.suffixes[‘.tar’, ‘.gz’](多扩展名)

我们可以通过以下代码获得需要的部分:

from pathlib import Path

p = Path("some/folder/file.txt")

print(p.name)       # 文件名:file.txt
print(p.stem)       # 主干名:file
print(p.suffix)     # 扩展名:.txt
print(p.parent)     # 父目录:some/folder
print(p.resolve())  # 返回绝对路径

路径的组合

通过pathlib我们不仅可以解析路径字符串,也能根据需要进行路径组合:

base = Path("/home/user")
full = base / "documents" / "file.txt"
print(full)  # 输出:/home/user/documents/file.txt

路径的判断

我们在开始使用路径时,往往需要进行一些必要的判断,如判断路径是否存在、是否是文件或目录:

print(p.exists())   # True / False
print(p.is_file())  # 是否为文件
print(p.is_dir())   # 是否为目录

3、目录的操作

创建、删除目录:

Path("data/logs").mkdir(parents=True, exist_ok=True)  # 递归创建目录
Path("data/logs").rmdir()                              # 删除空目录

递归删除目录

shutil模块的rmtree()函可以递归地删除目录及其子目录中的所有文件和目录,因此要谨慎使用。

import shutil  
shutil.rmtree("my_dir")

遍历当前目录下所有内容:

for item in Path(".").iterdir():
    print(item)

递归遍历当前目录及子目录的所有内容:

for path in Path(".").rglob("*"):
    print(path)

当然很多小伙伴可能更熟悉这种方式:

import os  
for root, dirs, files in os.walk("my_dir"):  
  for file in files:  
	  print(os.path.join(root, file))

递归查找 .txt 文件:

for file in Path(".").rglob("*.txt"):
    print(file)

glob 函数支持多种通配符来匹配文件路径模式,以下各种通配符的具体说明:

通配符含义说明示例
*匹配任意数量的字符(包括空字符),不跨目录*.txt 匹配所有 .txt 文件
?匹配任意单个字符file?.py 匹配 file1.py, fileA.py
[abc]匹配 a、b 或 c 中的任意一个字符file[12].txt 匹配 file1.txt, file2.txt
[a-z]匹配指定范围内的字符[a-z]*.md 匹配以小写字母开头的 .md 文件
[!abc]匹配不是 a、b 或 c 的字符(否定匹配)file[!3].txt 匹配除了 file3.txt 之外的
**匹配任意层级目录(用于递归)*.py 匹配当前目录及子目录中所有 .py 文件(需使用 rglob() 或 glob(“/”))

4、文件的操作

文件的操作主要借助于shutil库。

import shutil

src = Path("a.txt")
dst = Path("backup/b.txt")

src.rename(dst)       # 重命名或移动
dst.unlink()          # 删除文件
shutil.copy(src, dst) # 复制文件
shutil.copytree(Path("dir1"), Path("dir2"))  # 复制目录树

注意,使用unlink()删除文件时,它的意思是直接永久删除,如果只是需要放入操作系统的回收站或废纸篓可以使用第三方库send2trash

from send2trash import send2trash
from pathlib import Path

file = Path("important.txt")

if file.exists():
    send2trash(file)
    print("文件已移至回收站")
else:
    print("文件不存在")

5、文件的读写

文件信息与元数据

p = Path("example.txt")
info = p.stat()

print("大小:", info.st_size, "字节")
print("创建时间:", info.st_ctime)
print("修改时间:", info.st_mtime)

文件的读写

p = Path("notes.txt")

p.write_text("Hello, world!", encoding="utf-8")  # 写入文本
text = p.read_text(encoding="utf-8")             # 读取文本

p.write_bytes(b"binary data")  # 写入二进制
data = p.read_bytes()          # 读取二进制

当然很多小伙伴可能更熟悉这种方式:

import os

file_path = os.path.join("data", "example.txt")

# 确保目录存在
os.makedirs(os.path.dirname(file_path), exist_ok=True)

# 全部读取文本文件
with open(file_path, "r", encoding="utf-8") as f:
    content = f.read()
    print(content)
# 按行读取文本文件
with open(file_path, "r", encoding="utf-8") as f:
    for line in f:
        print("行内容:", line.strip())
# 写入文本文件
with open(file_path, "w", encoding="utf-8") as f:
    f.write("这是写入的内容\n第二行内容")

open() 函数包含了一个文件打开模式参数,其模式有以下几种:

模式含义
r以只读方式打开文本文件
w写入文本文件(覆盖原内容)
a追加到文本文件末尾
rb以二进制方式读取
wb以二进制方式写入(覆盖原内容)
x写入新文件(若文件已存在则报错)

6、文件/目录权限控制

权限代码

Python 中通常使用三位UNIX 风格的八进制整数(如 0o755),表示用户、用户组和其他人对文件/目录的操作权限。

rwxr-xr-- = 0o754
│ │ │
│ │ └── 其他用户权限:只读 (4)
│ └──── 组权限:可读+可执行 (5)
└────── 所有者权限:可读+写+执行 (7)

下面是一些常见权限模式:

模式八进制说明
rw-r–r–0o644普通文件,用户读写,组和其他只读
rwxr-xr-x0o755可执行脚本/程序,用户可读写执行
rw-------0o600私密文件,只有所有者读写权限
rwx------0o700私密目录或脚本,仅用户可执行

权限设置

我们可以使用 Path.chmod() 进行权限设置,使用 os.access() 进行权限检查。

import os

p = Path("example.txt")
p.chmod(0o600)                  # 设置为用户读写权限
print(os.access(p, os.R_OK))    # 判断是否可读

7、临时文件和目录

在程序中,有时候我们需要短暂使用文件系统存储,比如缓存、临时数据处理等,我们可以通过tempfile创建临时文件和临时目录

import tempfile

# 临时二进制文件
with tempfile.TemporaryFile() as tmp:
    tmp.write(b"Hello, temp!")
    tmp.seek(0)
    print(tmp.read())  # 输出:b'Hello, temp!'

# 临时文本文件
with tempfile.NamedTemporaryFile(mode='w+', encoding='utf-8', delete=True) as tmp:
    tmp.write("临时内容")
    tmp.seek(0)
    print(tmp.read())
    print(tmp.name)  # 查看临时文件路径

其中:
NamedTemporaryFile 会产生一个文件名路径,适合传递给其他程序使用。
delete=True 表示退出with时自动删除文件。

8、压缩与解压

压缩单一文件

import zipfile

with zipfile.ZipFile("archive.zip", "w") as z:
    z.write("example.txt")

压缩整个目录

shutil.make_archive()可以快速将整个目录打包成 .zip 或 .tar.gz 文件。

import shutil
# 参数说明:
# - base_name: 输出文件路径(不带扩展名)
# - format: 压缩格式,如 'zip', 'tar', 'gztar', 'bztar', 'xztar'
# - root_dir: 要打包的目录
shutil.make_archive("output/archive", "zip", root_dir="my_folder")

zipfile则可以灵活地控制哪些文件被压缩,或如何在压缩包中命名路径。

import zipfile
from pathlib import Path

def zip_dir(dir_path, zip_path):
    with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as z:
        for file in Path(dir_path).rglob("*"):
            if file.is_file():
                # 将文件添加到 zip 包,并保留相对路径结构
                z.write(file, arcname=file.relative_to(dir_path))

zip_dir("my_folder", "output/custom_archive.zip")

解压文件

import zipfile

with zipfile.ZipFile("archive.zip", "r") as z:
    z.extractall("unzipped/")
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值