pathlib 库中Path使用教程

传统上,Python使用常规文本字符串表示文件路径。由于路径不是字符串,重要的功能是遍布在标准库中的,包括像osglobshutil等库。从python3.4以后,pathlib内置,简化文件路径操作,pathlib可以看作os.path功能的一个面向对像化,从Python 3.6开始,添加了文件系统路径协议,整个标准库都支持pathlib模块。这里记录pathlib的Path方法的使用。

pathlib 库的 Path 方法,可以将一个普通的字符串转换为 pathlib.Path 对象类型的路径

Path的属性和方法

Path
│
├── Attributes
│       ├── parts
│       ├── parent & parents
│       ├── name
│       ├── suffix & suffixes
│       └── stem
│
│
└── Methods
        ├── joinpath(*other)
        ├── cwd()
        ├── home()
        ├── exists()
        ├── expanduser()
        ├── glob()
        ├── rglob(pattern)
        ├── is_dir()
        ├── is_file()
        ├── is_absolute()
        ├── iterdir()
        ├── mkdir(mode=0o777, parents=False, exist_ok=False)
        ├── open(mode='r', buffering=-1, encoding=None, errors=None, newline=None)
        ├── rename(target)
        ├── replace(target)
        ├── resolve(strict=False)
        └── rmdir()

创建路径

from pathlib import Path
 
now_path = Path.cwd()
home_path = Path.home()
 
print("当前工作目录",now_path,type(now_path))
print("home目录",home_path,type(home_path))

输出内容

当前工作目录 /Users/chennan/pythonproject/demo <class 'pathlib.WindowsPath'>
home目录 /Users/chennan <class 'pathlib.WindowsPath'>

或者传统方法,直接传入字符串

import pathlib
DIR_PATH = pathlib.Path("/Users/chennan/CDM")
print(DIR_PATH,type(DIR_PATH))

输出内容

/Users/chennan/CDM <class 'pathlib.WindowsPath'>

Path.mkdir(mode=0o777, parents=False, exist_ok=False)

在给定路径下创建新路径。

  • mode:文件的权限控制
  • parentes:如是是True,那么缺失的路径中的内容都会自动创建,否则会报FileNotFoundError的错
  • exist_ok:如果是False,那么当路径已经存在时,会报错;当是True时,会忽略报错
Path("src/other/side").mkdir(parents=True)

读写文件

可以通过“/”直接拼接路径,而且对于Path对象,可以直接使用open操作

import pathlib
DIR_PATH = pathlib.Path("/Users/wenxc/CDM") / "2000" / "hehe.txt"
with DIR_PATH.open("r") as fs:
     data = fs.read() 
print(data) 

对path对象也可以使用自身的文件读取方式,不再使用with open

.read_text(): 找到对应的路径然后打开文件,读成str格式。等同open操作文件的"r"格式。
.read_bytes(): 读取字节流的方式。等同open操作文件的"rb"格式。
.write_text(): 文件的写的操作,等同open操作文件的"w"格式。
.write_bytes(): 文件的写的操作,等同open操作文件的"wb"格式。

在使用相对路径时

import pathlib
py_path =pathlib.Path("superdemo.py")
print(py_path.resolve()) 

输出的是当前文件的相对路径

选择路径的不同组成部分

import pathlib
 
now_path = pathlib.Path.cwd() / "demo.txt"
print("name",now_path.name)
print("stem",now_path.stem)
print("suffix",now_path.suffix)
print("parent",now_path.parent)
print("anchor",now_path.anchor)

输出内容如下

name demo.txt
stem demo
suffix .txt
parent /Users/wenxc/pythonproject/demo
anchor /

移动和删除文件

使用 replace 方法可以移动文件,如果文件存在则会覆盖。为避免文件可能被覆盖,最简单的方法是在替换之前测试目标是否存在。

import pathlib
 
destination = pathlib.Path.cwd() / "target.txt" 
source = pathlib.Path.cwd() / "demo.txt"
if not destination.exists():
    source.replace(destination)

但是上面的方法存在问题就是,在多个进程多 destination 进行的操作的时候就会现问题,可以使用下面的方法避免这个问题。也就是说上面的方法适合单个文件的操作。

import pathlib
 
destination = pathlib.Path.cwd() / "target.txt" 
source = pathlib.Path.cwd() / "demo.txt"
with destination.open(mode='xb') as fid: 
    #xb表示文件不存在才操作
    fid.write(source.read_bytes())

当 destination文件存在的时候上面的代码就会出现 FileExistsError 异常。
从技术上讲,这会复制一个文件。 要执行移动,只需在复制完成后删除源即可。
使用 with_name 和 with.shuffix 可以修改文件名字或者后缀。

import pathlib
source = pathlib.Path.cwd() / "demo.py"
source.replace(source.with_suffix(".txt")) #修改后缀并移动文件,即重命名
#source依旧指向demo.py,不会变为demo.txt, 再次操作时注意区别

可以使用 .rmdir() 和 .unlink() 来删除文件。

import pathlib
 
destination = pathlib.Path.cwd() / "target" 
source = pathlib.Path.cwd() / "demo.txt"
source.unlink()

统计文件个数

import pathlib
from collections import Counter
now_path = pathlib.Path.cwd()
gen = (i.suffix for i in now_path.iterdir())
print(Counter(gen))

根据后缀统计文件夹内的文件数量

import pathlib
from  collections import Counter
gen =(p.suffix for p in pathlib.Path.cwd().glob('*.py'))
print(Counter(gen))

统计py文件的数量

glob和rglob的区别

#获取所有src/stuff文件夹下,以.py为后缀的文件
for fname in Path("src/stuff").glob("*.py"):
    print(fname)

src/stuff/__init__.py
src/stuff/submodule.py

# 比如要返回所有src文件夹下以.py为后缀的文件
for fname in Path("src").rglob("*.py"):
    print(fname)
    
src/module.py
src/b.py
src/stuff/__init__.py
src/stuff/submodule.py