Python pathlib – new in 3.4

By | 9月 26, 2023

pathlib是一个面向对象的文件系统路径,并且集成了文件的读写能力。只要使用 pathlib.Path 对象就可以了,其封装了操作系统的差异性,内部根据系统判断会生成PureWindowsPath或者PurePosixPath。

斜杠 / 拼接路径

拼接后还是Path对象,比os.path.join()代码简单,而且可读性好,用str()可将Path对象转换成路径字符串。

from pathlib import Path
etc = Path('/etc')
log = etc / 'work' / 'job' / 'log'
print(str(log))  # /etc/work/job/log

Path的类方法

Path.cwd() – 当前路径

对于可执行脚本来说,就是脚本所在的路径,等同于Path(‘.’) 或 Path()。

from pathlib import Path
current = Path.cwd()

import os
current_str = os.path.dirname(os.path.abspath(__file__))

print(str(current) == current_str)

Path.home() – home目录

from pathlib import Path
print(Path.home()) # C:\Users\Administrator

Path的常用属性

parent – 父路径

返回父路径的Path对象。

from pathlib import Path
p = Path('a/b/c/d')
print(p.parent)  # a/b/c

name = stem + suffix – 文件名

Path.name表示的是最后路径的字符串;如果是文件的话,Path.stem是去掉后缀的名字,suffix是文件后缀。

from pathlib import Path
p = Path('/my/library/setup.py')
print(p.name)   # setup.py
print(p.stem)   # setup
print(p.suffix) # .py

文件判断

exists() – 是否存在

返回True/False,表示文件是否存在。

from pathlib import Path
Path('.').exists() # True
Path('nonexistentfile').exists() # False

is_dir() – 是否是目录

判断文件是否存在且是目录。

is_file() – 是否是文件

判断文件是否存在且是文件。

is_symlink() – 是否是link

如果路径指向符号链接则返回 True, 否则 False

stat() – 详细信息

返回路径的详细信息。

from pathlib import Path
p = Path()
print(p.stat())
---------------------------------------------------------------------------------
os.stat_result(st_mode=16895, st_ino=19984723346525615, st_dev=239601270,
               st_nlink=1, st_uid=0, st_gid=0, st_size=4096, st_atime=1689777235, 
               st_mtime=1689777233, st_ctime=1689490618)

路径解析

expanduser() – 展开~和~user

返回一个新的Path对象,展开了~和~user。

from pathlib import Path
p = Path('~/films/Monty Python')
p = p.expanduser()
print(p.expanduser())
-----------------------
C:\Users\Administrator\films\Monty Python

resolve() – 绝对化且展开link

返回一个新的路径,将路径绝对化,解析任何符号链接。

from pathlib import Path
p = Path('docs/../setup.py')
p = p.resolve()
print(p) # /home/antoine/pathlib/setup.py

relative_to(other) – 相对路径

计算当前路径相对于other的相对路径。如果不可计算,则抛出ValueError。

from pathlib import Path
p = Path('/etc/passwd/ssd.txt')
q = p.relative_to('/etc')
print(q)  # passwd\ssd.txt

查找文件

iterdir() – 遍历目录

当路径指向一个目录时,产生该路径下的对象的路径。使用循环,可以深度遍历整个目录。

>>> p = Path('docs')
>>> for child in p.iterdir(): child
...
PosixPath('docs/conf.py')
PosixPath('docs/_templates')
PosixPath('docs/make.bat')
PosixPath('docs/index.rst')
PosixPath('docs/_build')
PosixPath('docs/_static')
PosixPath('docs/Makefile')

glob(pattern) – 查找文件

当前目录下查找py文件。

>>> sorted(Path('.').glob('*.py'))
[PosixPath('pathlib.py'), PosixPath('setup.py'), PosixPath('test_pathlib.py')]

一级子目录下查找py文件。

>>> sorted(Path('.').glob('*/*.py'))
[PosixPath('docs/conf.py')]

“**” 模式表示 “此目录以及所有子目录,递归”。换句话说,它启用递归通配:

>>> sorted(Path('.').glob('**/*.py'))
[PosixPath('build/lib/pathlib.py'),
 PosixPath('docs/conf.py'),
 PosixPath('pathlib.py'),
 PosixPath('setup.py'),
 PosixPath('test_pathlib.py')]

读写文件

open() – 打开文件

打开当前文件,和内置的open()函数因素。可选参数:(mode=’r’, buffering=-1, encoding=None, errors=None, newline=None)。

p = Path('setup.py')
with p.open() as f:
    f.readline()

read_bytes()

以字节对象的形式返回路径指向的文件的二进制内容:

>>> p = Path('my_binary_file')
>>> p.write_bytes(b'Binary file contents')
20
>>> p.read_bytes()
b'Binary file contents'

write_bytes(data)

文件不存在则自动创建,将文件以二进制模式打开,写入 data 并关闭:

>>> p = Path('my_binary_file')
>>> p.write_bytes(b'Binary file contents')
20
>>> p.read_bytes()
b'Binary file contents'

read_text(encoding=None, errors=None)

以字符串形式返回路径指向的文件的解码后文本内容。有和 open() 一样的可选形参。

>>> p = Path('my_text_file')
>>> p.write_text('Text file contents')
18
>>> p.read_text()
'Text file contents'

write_text(data, encoding=None, errors=None)

文件不存在则自动创建,将文件以文本模式打开,写入 data 并关闭。有和 open() 一样的可选形参。

>>> p = Path('my_text_file')
>>> p.write_text('Text file contents')
18
>>> p.read_text()
'Text file contents'

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

新建给定路径的目录。如果给出了 mode ,它将与当前进程的 umask 值合并来决定文件模式和访问标志。如果路径已经存在,则抛出 FileExistsError。

如果 parents 为真值,任何找不到的父目录都会伴随着此路径被创建;它们会以默认权限被创建,而不考虑 mode 设置(模仿 POSIX 的 mkdir -p 命令)。

如果 parents 为假值(默认),则找不到的父级目录会引发 FileNotFoundError。

如果 exist_ok 为 false(默认),则在目标已存在的情况下抛出 FileExistsError。

如果 exist_ok 为 true, 则 FileExistsError 异常将被忽略(和 POSIX mkdir -p 命令行为相同),但是只有在最后一个路径组件不是现存的非目录文件时才生效。

touch(self, mode=0o666, exist_ok=True)

Create this file with the given access mode, if it doesn’t exist.

rmdir()

删除此目录。此目录必须为空的。