好的,我们开始。
Python 文件操作:os
、pathlib
和 shutil
的高级用法
大家好!今天我们深入探讨 Python 中文件操作的三大模块:os
、pathlib
和 shutil
。我们将从基本概念出发,逐步介绍它们的高级用法,并通过实际代码示例来演示如何高效地处理文件和目录。
1. os
模块:系统级别的操作
os
模块提供了与操作系统交互的接口。它允许你执行诸如创建、删除、重命名文件和目录,以及获取文件信息等操作。虽然 pathlib
提供了更面向对象的路径处理方式,但在某些底层操作上,os
模块仍然是不可或缺的。
1.1 目录操作
-
创建目录:
os.mkdir()
和os.makedirs()
os.mkdir()
创建一个目录,但如果父目录不存在,则会抛出FileNotFoundError
异常。os.makedirs()
可以递归地创建目录,即使父目录不存在。import os # 创建单个目录 try: os.mkdir("my_directory") except FileExistsError: print("目录已存在") # 递归创建目录 os.makedirs("parent_directory/child_directory", exist_ok=True) # exist_ok=True 不抛出异常
-
删除目录:
os.rmdir()
和shutil.rmtree()
os.rmdir()
删除一个空目录。如果目录不为空,则会抛出OSError
异常。shutil.rmtree()
可以递归地删除整个目录树,包括所有文件和子目录。import os import shutil # 删除空目录 try: os.rmdir("my_directory") except OSError: print("目录非空或不存在") # 递归删除目录树 shutil.rmtree("parent_directory", ignore_errors=True) # 忽略错误
-
更改当前工作目录:
os.chdir()
os.chdir()
允许你更改 Python 程序的当前工作目录。import os print(f"当前工作目录:{os.getcwd()}") os.chdir("parent_directory") print(f"当前工作目录:{os.getcwd()}") os.chdir("..") # 返回上一级目录 print(f"当前工作目录:{os.getcwd()}")
-
列出目录内容:
os.listdir()
和os.scandir()
os.listdir()
返回一个包含目录中所有文件和子目录名称的列表。os.scandir()
返回一个迭代器,产生os.DirEntry
对象,这些对象包含有关每个文件或目录的更多信息,例如文件类型和大小。os.scandir()
通常比os.listdir()
更快,尤其是在处理大型目录时。import os # 使用 os.listdir() files = os.listdir(".") print(f"文件列表 (listdir): {files}") # 使用 os.scandir() with os.scandir(".") as entries: for entry in entries: print(f"文件名: {entry.name}, 是否是目录: {entry.is_dir()}, 文件大小: {entry.stat().st_size} bytes")
1.2 文件操作
-
重命名文件:
os.rename()
和os.renames()
os.rename()
重命名文件或目录。os.renames()
可以递归地创建中间目录,如果需要的话。import os # 重命名文件 try: with open("old_file.txt", "w") as f: f.write("This is a test file.") os.rename("old_file.txt", "new_file.txt") except FileNotFoundError: print("文件不存在") # 递归重命名 try: os.renames("a/b/old_file.txt", "a/c/new_file.txt") # 如果 a/c 不存在,则会创建 except FileNotFoundError: print("文件不存在")
-
删除文件:
os.remove()
os.remove()
删除指定的文件。import os # 删除文件 try: os.remove("new_file.txt") except FileNotFoundError: print("文件不存在")
-
获取文件信息:
os.stat()
os.stat()
返回一个包含文件信息的对象,例如大小、修改时间、权限等。import os import time # 创建一个示例文件 with open("example.txt", "w") as f: f.write("This is a test file.") # 获取文件状态信息 stat_info = os.stat("example.txt") print(f"文件大小:{stat_info.st_size} 字节") print(f"最后修改时间:{time.ctime(stat_info.st_mtime)}") print(f"权限:{stat_info.st_mode}") # 删除示例文件 os.remove("example.txt")
1.3 环境变量
os
模块可以访问和修改环境变量。
os.environ
:一个字典,包含当前的环境变量。os.getenv(varname, value=None)
:获取环境变量的值。如果变量不存在,返回value
,如果value
未指定,则返回None
。os.putenv(varname, value)
:设置环境变量的值。注意:这个函数可能会影响到其他进程。不推荐使用,推荐使用os.environ
直接修改字典。
import os
# 获取环境变量
home_dir = os.getenv("HOME")
print(f"Home 目录:{home_dir}")
# 设置环境变量 (不推荐)
# os.putenv("MY_VAR", "my_value") # 可能会影响其他进程
# 使用 os.environ 设置环境变量 (推荐)
os.environ["MY_VAR"] = "my_value"
print(f"MY_VAR: {os.environ['MY_VAR']}")
# 删除环境变量
del os.environ["MY_VAR"]
# print(f"MY_VAR: {os.environ['MY_VAR']}") # KeyError: 'MY_VAR'
1.4 进程管理
os
模块提供了一些基本的进程管理功能。
os.system(command)
:在子shell中执行命令。os.fork()
:创建一个新的进程。(仅在Unix系统上可用)os.execv(path, args)
:用新的程序替换当前进程。(仅在Unix系统上可用)
import os
# 执行系统命令
os.system("ls -l")
# 仅在Unix系统上可用
# pid = os.fork()
# if pid == 0:
# # 子进程
# os.execv("/bin/ls", ["ls", "-l"])
# else:
# # 父进程
# print(f"子进程 ID: {pid}")
# os.wait() # 等待子进程完成
2. pathlib
模块:面向对象的路径操作
pathlib
模块提供了一种面向对象的方式来操作文件和目录路径。它使用 Path
对象来表示路径,并提供了许多方便的方法来执行各种操作。
2.1 创建 Path 对象
from pathlib import Path
# 从字符串创建 Path 对象
path = Path("my_directory/my_file.txt")
# 从多个部分创建 Path 对象
path = Path("my_directory", "my_file.txt")
# 创建一个指向当前工作目录的 Path 对象
current_directory = Path(".")
# 创建一个指向用户主目录的 Path 对象
home_directory = Path.home()
print(f"Path 对象: {path}")
print(f"当前目录: {current_directory}")
print(f"Home 目录: {home_directory}")
2.2 路径操作
-
连接路径:
/
运算符可以使用
/
运算符来连接路径。from pathlib import Path parent_directory = Path("parent_directory") child_directory = Path("child_directory") file_path = parent_directory / child_directory / "my_file.txt" print(f"文件路径:{file_path}")
-
获取路径信息
from pathlib import Path path = Path("parent_directory/child_directory/my_file.txt") print(f"父目录:{path.parent}") print(f"文件名:{path.name}") print(f"不带后缀的文件名:{path.stem}") print(f"文件后缀:{path.suffix}") print(f"绝对路径:{path.resolve()}")
-
检查路径是否存在:
exists()
from pathlib import Path path = Path("parent_directory/child_directory/my_file.txt") if path.exists(): print("路径存在") else: print("路径不存在")
-
检查路径类型:
is_file()
和is_dir()
from pathlib import Path path = Path("parent_directory/child_directory/my_file.txt") if path.is_file(): print("是文件") elif path.is_dir(): print("是目录") else: print("既不是文件也不是目录")
-
创建目录:
mkdir()
from pathlib import Path path = Path("new_directory") path.mkdir(parents=True, exist_ok=True) # parents=True 递归创建,exist_ok=True 不抛出异常
-
删除文件或目录:
unlink()
和rmdir()
from pathlib import Path # 删除文件 file_path = Path("my_file.txt") file_path.unlink(missing_ok=True) # missing_ok=True 不抛出异常 # 删除目录 (必须为空) dir_path = Path("empty_directory") dir_path.rmdir()
-
遍历目录:
iterdir()
和glob()
iterdir()
返回一个迭代器,产生目录中的所有文件和子目录的Path
对象。glob()
允许你使用通配符来查找匹配特定模式的文件。from pathlib import Path # 创建一些示例文件和目录 Path("directory_1").mkdir(exist_ok=True) Path("directory_2").mkdir(exist_ok=True) Path("file_1.txt").touch() Path("file_2.txt").touch() Path("directory_1/file_3.txt").touch() # 使用 iterdir() directory = Path(".") for item in directory.iterdir(): print(item) # 使用 glob() for item in directory.glob("*.txt"): print(item) for item in directory.glob("**/*.txt"): # 递归查找 print(item) # 清理示例文件和目录 import shutil shutil.rmtree("directory_1", ignore_errors=True) shutil.rmtree("directory_2", ignore_errors=True) Path("file_1.txt").unlink(missing_ok=True) Path("file_2.txt").unlink(missing_ok=True)
2.3 文件读写
pathlib
提供了方便的方法来读取和写入文件。
-
读取文件:
read_text()
和read_bytes()
from pathlib import Path # 创建一个示例文件 file_path = Path("my_file.txt") file_path.write_text("Hello, world!") # 读取文本文件 content = file_path.read_text() print(f"文件内容:{content}") # 读取二进制文件 binary_content = file_path.read_bytes() print(f"文件内容(二进制):{binary_content}") # 删除示例文件 file_path.unlink()
-
写入文件:
write_text()
和write_bytes()
from pathlib import Path # 创建一个 Path 对象 file_path = Path("my_file.txt") # 写入文本文件 file_path.write_text("Hello, world!") # 写入二进制文件 file_path.write_bytes(b"Hello, world!") # 删除示例文件 file_path.unlink()
3. shutil
模块:高级文件操作
shutil
模块提供了许多高级的文件操作,例如复制、移动、重命名和删除文件和目录树。它通常用于执行更复杂的文件管理任务。
3.1 文件复制
shutil.copy(src, dst)
:复制文件src
到dst
。目标可以是文件或目录。如果dst
是目录,则文件将复制到该目录中,并保留原始文件名。只复制文件内容和权限。shutil.copy2(src, dst)
:与copy()
类似,但还会复制文件的元数据,例如最后访问时间和修改时间。shutil.copytree(src, dst)
:递归地复制整个目录树。
import shutil
from pathlib import Path
# 创建一些示例文件和目录
Path("source_directory").mkdir(exist_ok=True)
Path("source_directory/file_1.txt").touch()
Path("source_file.txt").touch()
# 复制文件
shutil.copy("source_file.txt", "destination_file.txt")
shutil.copy2("source_file.txt", "destination_file_2.txt") # 复制元数据
shutil.copy("source_file.txt", "source_directory") # 复制到目录
# 复制目录树
shutil.copytree("source_directory", "destination_directory")
# 清理示例文件和目录
Path("destination_file.txt").unlink()
Path("destination_file_2.txt").unlink()
shutil.rmtree("source_directory", ignore_errors=True)
shutil.rmtree("destination_directory", ignore_errors=True)
Path("source_file.txt").unlink()
3.2 文件移动和重命名
shutil.move(src, dst)
:移动文件或目录src
到dst
。如果dst
已经存在,并且是目录,则src
将移动到该目录中。如果dst
存在且是文件,则会被覆盖。
import shutil
from pathlib import Path
# 创建一些示例文件和目录
Path("source_file.txt").touch()
Path("source_directory").mkdir(exist_ok=True)
# 移动文件
shutil.move("source_file.txt", "destination_file.txt") # 重命名
shutil.move("destination_file.txt", "source_directory") # 移动到目录
# 清理示例文件和目录
shutil.rmtree("source_directory", ignore_errors=True)
3.3 文件和目录删除
shutil.rmtree(path, ignore_errors=False, onerror=None)
:递归地删除整个目录树。如果ignore_errors
为True
,则忽略删除错误。如果onerror
提供,它应该是一个可调用对象,接受三个参数:function
,path
, andexcinfo
。
import shutil
from pathlib import Path
# 创建一个示例目录树
Path("my_directory/child_directory").mkdir(parents=True, exist_ok=True)
Path("my_directory/file_1.txt").touch()
Path("my_directory/child_directory/file_2.txt").touch()
# 递归删除目录树
shutil.rmtree("my_directory", ignore_errors=True)
3.4 归档操作
shutil
模块还提供了一些归档操作,例如创建和提取 ZIP 文件和 tar 文件。
shutil.make_archive(base_name, format, root_dir=None, base_dir=None)
:创建一个归档文件。shutil.unpack_archive(filename, extract_dir=None, format=None)
:提取归档文件。
import shutil
from pathlib import Path
# 创建一些示例文件和目录
Path("my_directory/child_directory").mkdir(parents=True, exist_ok=True)
Path("my_directory/file_1.txt").touch()
Path("my_directory/child_directory/file_2.txt").touch()
# 创建 ZIP 归档
shutil.make_archive("my_archive", "zip", root_dir=".") # 将当前目录下的所有内容归档
# 提取 ZIP 归档
shutil.unpack_archive("my_archive.zip", extract_dir="extracted_directory")
# 清理示例文件和目录
shutil.rmtree("my_directory", ignore_errors=True)
shutil.rmtree("extracted_directory", ignore_errors=True)
Path("my_archive.zip").unlink()
3.5 磁盘空间
shutil
模块提供获取磁盘空间使用情况的函数。
shutil.disk_usage(path)
:返回一个命名元组,包含总空间、已用空间和可用空间。
import shutil
total, used, free = shutil.disk_usage(".")
print(f"总空间: {total // (2**30)} GB")
print(f"已用空间: {used // (2**30)} GB")
print(f"可用空间: {free // (2**30)} GB")
模块 | 主要功能 | 优点 | 缺点 |
---|---|---|---|
os |
系统级别的文件和目录操作,环境变量,进程管理。 | 底层操作,功能强大,与操作系统交互紧密。 | 路径处理比较繁琐,需要手动拼接字符串,错误处理需要更多代码。 |
pathlib |
面向对象的路径操作,文件读写。 | 面向对象,代码更简洁易读,提供更多方便的方法,更容易处理跨平台路径问题。 | 某些底层操作不如 os 模块直接。 |
shutil |
高级文件操作,例如复制、移动、重命名、删除、归档。 | 提供高级功能,简化复杂的文件管理任务,例如递归复制目录树。 | 功能相对较少,主要集中在文件管理方面。 |
总结一下三个模块的特点
os
提供底层系统交互,pathlib
提供面向对象的路径处理,shutil
提供高级文件操作功能。三者结合使用,可以高效地完成各种文件管理任务。选择哪个模块取决于具体的任务需求和个人偏好。通常,pathlib
是首选,因为它更易于使用,但在需要底层操作时,os
仍然是必要的。shutil
则用于处理更高级的文件管理任务。
希望今天的讲解对大家有所帮助!