pathlib 文件操作模块
阅读需要 15分钟。
- 之使用 python 操作文件路径,最苦开始使用 os.path。
- pathlib 库从 python3.4 开始,到 python3.6 已经比较成熟。
为什么会有pathlib模块:规范统一
- 老的路径操作函数比较混乱, os, os.path 当中,现在统一可以用 pathlib 管理。
- 老的API对于不同操作系统的处理 win,mac 以及 linux 不方便
- 老方法使用的是函数,返回的路径通常是个”字符串“,但是字符串还是路径
- pathlib 使用简单功能丰富。
pathlib使用 import mathlob 或者 from pathlib import Path
from pathlib import Path
当前目录在哪里
from pathlib import Path
pwd = Path.cwd()
print(pwd)
home目录
from pathlib import Path
pwd = Path.cwd()
print(pwd)
print(Path.home())
C:\Users\admin
home目录在Windows上通常是 c:/User/用户名 这个目录,而Linux通常也是用户的主目录
下面是一个linux服务器上root用户的home目录 /root
Paht的各种用法
- 根据字符串构建目录: Path(r"C:\Users\philipp\realpython\file.txt")
p =Path(r"C:\Users\philipp\realpython\file.txt")
print(p,)
print(p.parent) # 获取上级目录
C:\Users\philipp\realpython\file.txt
C:\Users\philipp\realpython
Path对象的parent方法可以找到它的上层目录,一直可以找到最上层的根目录
- 获取当前执行的Python文件的完整路径和目录
print(Path(__file__))
print(Path(__file__).parent)
- 移动文件:比如将某个目录下的 txt文本文件移到到其他目录
for file_path in Path.cwd().glob("*.txt"):
# new_path = Path("archive",file_path.name)
new_path = Path("archive") / file_path.name
#以上两种方式都是构建新目录文件 的路径,效果是一样的
print(new_path)
file_path.rename(new_path)
- 组合文件路径 joinpath
a = Path.home().joinpath("python", "scripts", "test.py")
print(a)
Paht对象的关键组件
- .name: 文件名,没有目录路径 a.txt
- .stem: 没有扩展名的文件名 a
- .suffix: 文件后缀
- .anchor: 文件作者
- .parent: 父目录
>>> from pathlib import Path
>>> path = Path(r"C:\Users\gahjelle\realpython\test.md")
>>> path
WindowsPath('C:/Users/gahjelle/realpython/test.md')
>>> path.name
'test.md'
>>> path.stem
'test'
>>> path.suffix
'.md'
>>> path.anchor
'C:\\'
>>> path.parent
WindowsPath('C:/Users/gahjelle/realpython")
>>> path.parent.parent
WindowsPath('C:/Users/gahjelle')
使用 / 斜杠 连接目录如下
path.parent.parent / f"new{path.suffix}"
PosixPath('/home/gahjelle/new.md')
读取文件
假设有一个文件 的内容如下
<!-- shopping_list.md -->
# Shopping List
## Fruit
* Banana
* Apple
* Peach
## Candy
* Chocolate
* Nougat Bits
# read_shopping_list.py
from pathlib import Path
path = Path.cwd() / "shopping_list.md"
with path.open(mode="r", encoding="utf-8") as md_file:
content = md_file.read()
groceries = [line for line in content.splitlines() if line.startswith("*")]
print("\n".join(groceries))
- .read_text() 字符串方式读取文件
- .read_bytes() 二进制方式读取文件
- .write_text() 写入文本到 文件
- .write_bytes() 写入二进制数据到 文件
from pathlib import Path
path = Path.cwd() / "shopping_list.md"
content = path.read_text(encoding="utf-8")
groceries = [line for line in content.splitlines() if line.startswith("*")]
print("\n".join(groceries))
#写文件
Path("plain_list.md").write_text("\n".join(groceries), encoding="utf-8")
重命名文件
>>> from pathlib import Path
>>> txt_path = Path("/home/gahjelle/realpython/hello.txt")
>>> txt_path
PosixPath("/home/gahjelle/realpython/hello.txt")
>>> md_path = txt_path.with_suffix(".md")
PosixPath('/home/gahjelle/realpython/hello.md')
>>> txt_path.replace(md_path)
with_suffix 构建一个新的Paht 把 .txt 后缀修改为 .md
使用 replace函数把电脑上的文件名重新命名
复制文件:其中一种办法 内容复制创建新文件
>>> source = Path("shopping_list.md")
>>> destination = source.with_stem("shopping_list_02")
>>> destination.write_bytes(source.read_bytes())
创建新文件 touch 函数
>>> from pathlib import Path
>>> filename = Path("hello.txt")
>>> filename.exists()
False
>>> filename.touch()
>>> filename.exists()
True
>>> filename.touch()
如果文件已经存在,调用touch函数时exist_ok为False则会报错。
>>> filename.touch(exist_ok=False)
Traceback (most recent call last):
...
FileExistsError: [Errno 17] File exists: 'hello.txt'
Pathlib应用小例子
统计不同文件类型的数量
>>> from pathlib import Path
>>> from collections import Counter
>>> Counter(path.suffix for path in Path.cwd().iterdir())
Counter({'.md': 2, '.txt': 4, '.pdf': 2, '.py': 1})
>>> from collections import Counter
>>> Counter(path.suffix for path in Path.cwd().iterdir())
Counter({'': 8, '.dll': 4, '.txt': 2, '.exe': 2})
>>>
显示目录的树形结构
def tree(directory):
print(f"+ {directory}")
for path in sorted(directory.rglob("*")):
depth = len(path.relative_to(directory).parts)
spacer = " " * depth
print(f"{spacer}+ {path.name}")
查找最近修改的文件
>> from pathlib import Path
>>> from datetime import datetime
>>> directory = Path.cwd()
>>> time, file_path = max((f.stat().st_mtime, f) for f in directory.iterdir())
>>> print(datetime.fromtimestamp(time), file_path)
2022-04-03 09:30:57.448853 C:\Users\admin\AppData\Local\Programs\Python\Python38\Scripts
>>>
创建唯一的文件名,不重名
def unique_path(directory, name_pattern):
counter = 0
while True:
counter += 1
path = directory / name_pattern.format(counter)
if not path.exists():
return path
代码很简单实际上就是有一个计数器 counter作为文件名中的一部分如果存在同名的文件,counter 加1 直到没有重复的名字。