![3412698c81132766bdcea07610997f00.png](https://i-blog.csdnimg.cn/blog_migrate/d3298bb7f82ef60de9b60e806189cd61.jpeg)
使用面向对象的 API 而不是低级字符串操作来解析,构建,测试和以其他方式处理文件名和路径。
构建路径
要创建引用相对于现有路径值的新路径,可以使用 / 运算符来扩展路径,运算符的参数可以是字符串或其他路径对象。
import pathlibusr = pathlib.PurePosixPath('/usr')print(usr) # /usrusr_local = usr / 'local'print(usr_local) # /usr/localusr_share = usr / pathlib.PurePosixPath('share')print(usr_share) # /usr/shareroot = usr / '..'print(root) # /usr/..etc = root / '/etc/'print(etc) # /etc
正如root示例所示,运算符在给定路径值时将它们组合在一起,并且在包含父目录引用时不会对结果进行规范化 ".."。但是,如果某段以路径分隔符开头,则会以与之相同的方式将其解释为新的“根”引用 os.path.join(),从路径值中间删除额外路径分隔符,如此处的etc示例所示。
路径类包括 resolve() 方法,通过查看目录和符号链接的文件系统以及生成名称引用的绝对路径来规范化路径。
import pathlibusr_local = pathlib.Path('/usr/local')share = usr_local / '..' / 'share'print(share.resolve()) # /usr/share
这里相对路径转换为绝对路径 /usr/share。如果输入路径包含符号链接,那么也会扩展这些符号链接以允许已解析的路径直接引用目标。
要在事先不知道段时构建路径,请使用 joinpath(),将每个路径段作为单独的参数传递。
import pathlibroot = pathlib.PurePosixPath('/')subdirs = ['usr', 'local']usr_local = root.joinpath(*subdirs)print(usr_local) # /usr/local
与/运算符一样,调用joinpath()会创建一个新实例。
给定一个现有的路径对象,很容易构建一个具有微小差异的新对象,例如引用同一目录中的不同文件,使用with_name()创建替换文件名的新路径。使用 with_suffix()创建替换文件扩展名的新路径。
import pathlibind = pathlib.PurePosixPath('source/pathlib/index.rst')print(ind) # source/pathlib/index.rstpy = ind.with_name('pathlib_from_existing.py')print(py) # source/pathlib/pathlib_from_existing.pypyc = py.with_suffix('.pyc')print(pyc) # source/pathlib/pathlib_from_existing.pyc
两种方法都返回新对象,原始文件保持不变。
解析路径
Path 对象具有从名称中提取部分值的方法和属性。例如,parts 属性生成一系列基于路径分隔符解析的路径段。
import pathlibp = pathlib.PurePosixPath('/usr/local')print(p.parts) # ('/', 'usr', 'local')
序列是一个元组,反映了路径实例的不变性。
有两种方法可以从给定的路径对象“向上”导航文件系统层次结构。parent 属性引用包含路径的目录的新路径实例,通过 os.path.dirname() 返回值。parents 属性是一个可迭代的,它产生父目录引用,不断地“向上”路径层次结构,直到到达根目录。
import pathlibp = pathlib.PurePosixPath('/usr/local/lib')print('parent: {}'.format(p.parent))print('hierarchy:')for up in p.parents: print(up)# output# parent: /usr/local# # hierarchy:# /usr/local# /usr# /
该示例遍历parents属性并打印成员值。
可以通过路径对象的属性访问路径的其他部分。name 属性保存路径的最后一部分,位于最终路径分隔符(os.path.basename() 生成的相同值)之后。suffix属性保存扩展分隔符后面的值,stem属性保存后缀之前的名称部分。
import pathlibp = pathlib.PurePosixPath('./source/pathlib/pathlib_name.py')print('path : {}'.format(p)) # path : source/pathlib/pathlib_name.pyprint('name : {}'.format(p.name)) # name : pathlib_name.pyprint('suffix: {}'.format(p.suffix)) # suffix: .pyprint('stem : {}'.format(p.stem)) # stem : pathlib_name
虽然suffix和stem值类似于 os.path.splitext() 生成的值,但值仅基于 name 而不是完整路径。
创建具体路径
Path 可以从引用文件系统上的文件,目录或符号链接名称(或潜在名称)的字符串创建具体类的实例。该类还提供了几种方便的方法,用于使用常用的更改位置(例如当前工作目录和用户的主目录)构建实例。
import pathlibhome = pathlib.Path.home()print('home: ', home) # home: /Users/dhellmanncwd = pathlib.Path.cwd()print('cwd : ', cwd) # cwd : /Users/dhellmann/PyMOTW
目录内容
有三种方法可以访问目录列表,以发现文件系统上可用文件的名称。iterdir() 是一个生成器,Path 为包含目录中的每个项生成一个新实例。
import pathlibp = pathlib.Path('.')for f in p.iterdir(): print(f)# output# example_link# index.rst# pathlib_chmod.py# pathlib_convenience.py# pathlib_from_existing.py# pathlib_glob.py# pathlib_iterdir.py# pathlib_joinpath.py# pathlib_mkdir.py# pathlib_name.py
如果Path不引用目录,则iterdir() 引发NotADirectoryError。
glob() 仅查找与模式匹配的文件。
import pathlibp = pathlib.Path('..')for f in p.glob('*.rst'): print(f)# output# ../about.rst# ../algorithm_tools.rst# ../book.rst# ../compression.rst# ../concurrency.rst# ../cryptographic.rst# ../data_structures.rst# ../dates.rst# ../dev_tools.rst# ../email.rst
glob 处理器支持使用模式前缀进行递归扫描 **或通过调用rglob()而不是glob()。
import pathlibp = pathlib.Path('..')for f in p.rglob('pathlib_*.py'): print(f)# output# ../pathlib/pathlib_chmod.py# ../pathlib/pathlib_convenience.py# ../pathlib/pathlib_from_existing.py# ../pathlib/pathlib_glob.py# ../pathlib/pathlib_iterdir.py# ../pathlib/pathlib_joinpath.py# ../pathlib/pathlib_mkdir.py# ../pathlib/pathlib_name.py# ../pathlib/pathlib_operator.py# ../pathlib/pathlib_ownership.py# ../pathlib/pathlib_parents.py
由于此示例从父目录开始,因此需要进行递归搜索以查找匹配的示例文件 pathlib_*.py。
读写文件
每个 Path 实例都包含用于处理它所引用的文件内容的方法。要读取内容,使用 read_bytes() 或 read_text()。要写入文件,使用 write_bytes() 或 write_text()。
使用 open() 方法打开文件并保留文件句柄,而不是将名称传递给内置 open() 函数。
import pathlibf = pathlib.Path('example.txt')f.write_bytes('This is the content'.encode('utf-8'))with f.open('r', encoding='utf-8') as handle: print('read from open(): {!r}'.format(handle.read()))print('read_text(): {!r}'.format(f.read_text('utf-8')))# output# read from open(): 'This is the content'# read_text(): 'This is the content'
操作目录和符号链接
import pathlibp = pathlib.Path('example_dir')print('Creating {}'.format(p))p.mkdir()# output# Creating example_dir# Traceback (most recent call last):# File "pathlib_mkdir.py