编写访问目录及文件的代码是最常见的开发工作之一,如何快速方便地操作路径?pathlib 也许是一个很理想的工具。
pathlib 是Python内置库,Python 文档给它的定义是 Object-oriented filesystem paths(面向对象的文件系统路径)。pathlib 提供表示文件系统路径的类,其语义适用于不同的操作系统。
pathlib 不直接访问 OS 来操作 path,占内存少, 不用考虑底层是Linux还是Windows, 使代码可移植性更佳。
通常, pathlib.Path 类就可以满足绝大部分场景使用。 当然如果只是 windows 应用开发,可以直接使用 PureWindowsPath, WindowsPath 等子类来编程,没必要化简就繁,毕竟 Path 类更通用。
from pathlib import Path # 导入 pathlib Path 模块
print( Path.cwd()) # **获取当前路径
从路径中分解文件名
>>> p1 = Path("E:\智慧社区\tmp\log\2020-7-24\property.log")
>>> p1
WindowsPath('E:/智慧社区\tmp/log\x8s20-7-24/property.log')
>>> print(p1.stem) # 获取文件名(不带扩展名)
property
>>> print(p1.name) # 文件名 全名
property.log
>>> print(p1.suffix) # 文件名后缀
.log
>>> print(p1.anchor)
E:\
>>> print(p1.suffixes)
['.log']
用parents 属性来分解路径目录
>>> str(p1.parent) # 获取当 path的完整目录名,不含文件名
'E:\\智慧社区\\tmp\\log\\2020-7-24'
# 获得各级目录名称,注意Path.parents[] ,多了1个s
>>> p1.parents[0]
WindowsPath('E:/智慧社区/tmp/log/2020-7-24')
>>> p1.parents[1]
WindowsPath('E:/智慧社区/tmp/log')
>>> p1.parents[2]
WindowsPath('E:/智慧社区/tmp')
>>> p1.parents[3]
WindowsPath('E:/智慧社区')
>>> p1.parents[4]
WindowsPath('E:/')
>>> p1.parents
path 路径的分解也可以用 parts
方法
返回各目录元组
>>> p = PurePath('/usr/bin/python3')
>>> p.parts
('/', 'usr', 'bin', 'python3')
>>> p = PureWindowsPath('c:/Program Files/PSF')
>>> p.parts
('c:\\', 'Program Files', 'PSF')
PurePath 是 Path 的父类,所以 Path 对象也可以直接使用 parts 方法
>>> p = Path('.')
>>> [x for x in p.iterdir() if x.is_dir()]
[PosixPath('.hg'), PosixPath('docs'), PosixPath('dist'),
PosixPath('__pycache__'), PosixPath('build')]
glob() 方法返回列表,元素也是Path类型
rglob() 方法可获取当前目录及所有子目录的相关内容
>>> list(p.glob('**/*.py'))
[PosixPath('test_pathlib.py'), PosixPath('setup.py'),
PosixPath('pathlib.py'), PosixPath('docs/conf.py'),
PosixPath('build/lib/pathlib.py')]
用 / 操作符,或joinpath()方法,其结果仍是Path类型
强烈建议使用path的路径拼接功能,避免使用str 变量相加来组合,容易出错。
>>> p = Path('/etc')
>>> q = p / 'init.d' / 'reboot'
>>> q
PosixPath('/etc/init.d/reboot')
>>> q.resolve()
PosixPath('/etc/rc.d/init.d/halt')
>>> z = p.joinpath("1.conf")
PosixPath('/etc/1.conf')
>>> q.exists() # 路径是否存在
True
>>> q.is_dir() # 是否为目录
False
>>> q.is_file() # 是否为文件
True
Path.resolve()
>>> p = Path()
>>> p
PosixPath('.')
>>> p.resolve()
PosixPath('/home/antoine/pathlib')
当需要 print 或 把path做为 string 传递给一些函数时,需要把path 对象 转成 string后使用。 Windows下会自动使用 双反斜杠 \\
也可以使用Path类的内置方法__str__() 来获取其string值
>>> p = PurePath('/etc')
>>> str(p)
'/etc'
>>> p = PureWindowsPath('c:/Program Files')
>>> str(p)
'c:\\Program Files'
>>> q = Path("/home/peter/lianxi/p1.py")
PosixPath('/home/peter/lianxi/p1.py')
>>> q.__str__()
'/home/peter/lianxi/p1.py'
用更少语句完成文件操作, 可避免转换成string, 再用python 方法 open 打开文件的过程。
>>> with q.open() as f: f.readline()
...
'#!/bin/bash\n'
pathlib.PurePath 不直接访问OS, 更有利于跨操作系统编程。 Path 是其子类
>>> PurePath('setup.py') # Running on a Unix machine
PurePosixPath('setup.py') # 表明运行在 Linux 上,底层自动用linux的目录
>>>PurePath('foo', 'some/path', 'bar')
PurePosixPath('foo/some/path/bar')
>>> PurePath('/etc', '/usr', 'lib64')
PurePosixPath('/usr/lib64')
>>> PurePosixPath('foo') == PurePosixPath('FOO')
False
>>> p = PurePath('/etc')
>>> p
PurePosixPath('/etc')
>>> p / 'init.d' / 'apache2'
PurePosixPath('/etc/init.d/apache2')
>>> q = PurePath('bin')
>>> '/usr' / q
PurePosixPath('/usr/bin')
PurePath.as_posix()
返回 Linux风格的路径 (/
):
PurePath.is_absolute()
判断当前路径是否为绝对路径
>>> PureWindowsPath('//some/share').is_absolute()
True
PurePath.joinpath( )
与 / 操作符的功能类似,用于路径拼接
>>> PurePosixPath('/etc').joinpath('passwd')
PurePosixPath('/etc/passwd')
>>> PurePosixPath('/etc').joinpath(PurePosixPath('passwd'))
PurePosixPath('/etc/passwd')
>>> PurePosixPath('/etc').joinpath('init.d', 'apache2')
PurePosixPath('/etc/init.d/apache2')
PurePath.match`(pattern)
判断 pattern 是否在目录路径内
如果匹配到了, 返回True,
>>> PurePath('a/b.py').match('*.py')
True
>>> PurePath('/a/b/c.py').match('b/*.py')
True
>>> PurePath('/a/b/c.py').match('a/*.py')
False
PurePath.with_name`(filename)
检查 访路径是否包含文件名
如果原路径不包含该文件名,则生成 ValueError 异常
>>> p = PureWindowsPath('c:/Downloads/pathlib.tar.gz')
>>> p.with_name('setup.py')
PureWindowsPath('c:/Downloads/setup.py')
Patth是 PurePath的子类, 这个类代表 concrete path 实体路径
除了继承PurePath的方法外,下面表格列出来 Path的常用方法,以及与os 相关方法的对应关系,
os and os.path | pathlib |
---|---|
os.path.abspath() | Path.resolve() |
os.chmod() | Path.chmod() |
os.mkdir() | Path.mkdir() |
os.makedirs() | Path.mkdir() |
os.rename() | Path.rename() |
os.replace() | Path.replace() |
os.rmdir() | Path.rmdir() |
os.remove(), os.unlink() | Path.unlink() |
os.getcwd() | Path.cwd() |
os.path.exists() | Path.exists() |
os.path.expanduser() | Path.expanduser() and Path.home() |
os.listdir() | Path.iterdir() |
os.path.isdir() | Path.is_dir() |
os.path.isfile() | Path.is_file() |
os.path.islink() | Path.is_symlink() |
os.link() | Path.hardlink_to() |
os.symlink() | Path.symlink_to() |
os.readlink() | Path.readlink() |
os.path.relpath() | Path.relative_to() 2 |
os.stat() | Path.stat(), Path.owner(), Path.group() |
os.path.isabs() | PurePath.is_absolute() |
os.path.join() | PurePath.joinpath() |
os.path.basename() | PurePath.name |
os.path.dirname() | PurePath.parent |
os.path.samefile() | Path.samefile() |
os.path.splitext() | PurePath.suffix |
Path 方法读写文件,可区分 Ascii 与 bytes 方式,编程效率更高
>>> p = Path('setup.py')
>>> with p.open() as f:
... f.readline()
>>> target.open().read()
'some text'
>>> p = Path('foo')
>>> p.open('w').write('some text')
9
>>> p = Path('my_text_file')
>>> p.write_text('Text file contents')
18
>>> p.read_text()
'Text file contents'
>>> p = Path('my_binary_file')
>>> p.write_bytes(b'Binary file contents')
20
>>> p.read_bytes()
b'Binary file contents'
>>> p = Path('foo')
>>> p.open('w').write('some text')
9
>>> target = Path('bar')
>>> p.rename(target)
PosixPath('bar')
>>> target.open().read()
'some text'
Path.unlink (missing_ok=False)
Remove this file or symbolic link. If the path points to a directory, use Path.rmdir() instead.
默认 missing_ok = False, 如果文件不存在,会产生 FileNotFoundError 异常,设置为True, 则忽略该异常。
Path.mkdir() 生成子目录
>>> p1 = Path('/home/peter/lianxi')
>>> p3=p1/'test'
>>> p3.exists()
False
>>> p3.mkdir()
>>> p3.exists()
True
>>> p3
PosixPath('/home/peter/lianxi/test')
如上一级目录不存在,将产生1个 FileNotFoundError异常。
如目标目录已经存在,将产生1个 FileExistsError 异常
Path.rmdir() 删除目录, 该目录必须为空
pathlib 可以用于替换 os.path 功能,并且更适用于跨平台编程,还提供了更高效的文件操作方式,值得学习。