os.path — 路径操作

os.path 模块常用于解析、构建、测试以及处理文件名和路径,用于开发跨平台的程序。

路径参数可以是字符串也可以是字节,应该首选将文件名称表示为(Unicode)字符串。不幸的是,一些文件的名称可能不可以在 Unix 上表示为字符串,所以需要在 Unix 上支持任意文件名的程序应使用字节对象来表示路径名。反之亦然,使用字节对象不能表示所有 Windows 上的文件名 (在标准 mbcs 编码),因此在 Windows 程序中应使用字符串对象来访问所有文件。

Note

所有的参数仅接受只有字节或只有字符串对象,不可以传入两种对象参数。在返回路径或文件名时,结果与传入参数的类型相同。

有时候,路径解析会依赖于定义在 os 中的一些变量:

  • os.sep – 路径各部分之间的分隔符 (例如, 在 win 平台下的 \\ 和在 Linux 平台下的 /

  • os.extsep – 文件名和 「扩展名」之间的分隔符 (例如, .

  • os.pardir – 表示上级目录的路径组件(例如, ..

  • os.curdir – 表示当前目录的路径组件(例如, .

解析路径

os.path 中有一组函数用于将表示文件名称的字符串解析成它的组成部分,这些函数不依赖于实际存在的路径,它们只能用来操作字符串。

os.path.split(path) 分离路径和文件名。将路径名 path 拆分为一个元组对 (head, tail),其中 tail 是路径名的最后一个部分,head 是前面的所有内容。tail 部分不会包含斜杠;如果 path 以斜线结尾,则 tail 将为空。如果 path 中没有斜线,head 将为空。如果 path 为空,head 和 tail 两个都将为空。尾部的斜线会从 head 中去除掉,除非它是根目录(只包含一个或多个斜线的目录)。

>>> os.path.split('/usr/lib/python3.6')
('/usr/lib', 'python3.6')
>>> os.path.split('/usr/lib/python3.6/')
('/usr/lib/python3.6', '')
>>> os.path.split('/usr/lib/python3.6/pp.py')
('/usr/lib/python3.6', 'pp.py')

os.path.basename(path) 返回路径名 path 的最后一级的名称(等同于 split() 函数 tail 部分的值)。

>>> os.path.basename('/usr/lib')
'lib'

>>> os.path.basename('/usr/lib/')
''
>>> os.path.basename('/usr/lib/python3/pp.py')
'pp.py'

os.path.dirname(path) 返回 path 中的目录名(等同于 split() 函数 head 部分的值)。

>>> os.path.dirname('/usr/lib/python3/pp.py')
'/usr/lib/python3'
>>> os.path.dirname('/usr/lib/')
'/usr/lib'
>>> os.path.dirname('/usr/lib')
'/usr'

os.path.splitext(path) 分离文件名和后缀名。为避免出现不可预测的结果,最好不要带有路径。

>>> os.path.splitext('/usr/lib/python3/pp.py')
('/usr/lib/python3/pp', '.py')
>>> os.path.splitext('pp.py')
('pp', '.py')
>>> os.path.splitext('abc.tar.gz')
('abc.tar', '.gz')
>>> os.path.splitext('/usr/lib/python3.6/')
('/usr/lib/python3.6/', '')
>>> os.path.splitext('/usr/lib/python3.6')
('/usr/lib/python3', '.6')

构建路径

os.path.join(path, *paths) 将一个或多个路径连接起来。如果某个参数是以 os.sep 开头,那么它之前的所有参数都将被丢弃,并且返回值将以它作为新的开始。。

>>> os.path.join('usr', 'lib', 'python3')
'usr/lib/python3'
>>> os.path.join('/usr/', 'lib/python3/')
'/usr/lib/python3/'
>>> os.path.join('/usr', 'lib/python3/')
'/usr/lib/python3/'
>>> os.path.join('/usr/', '/lib/python3/')
'/lib/python3/'

os.path.expanduser(path) 在 Unix 和 Windows 上,将参数中原始的 ~ 或 ~user 部分用 user 主目录替换。如果扩展失败或者参数不以 ~ 开头,则返回 path 不变。

>>> os.path.expanduser('~/Document')
'/home/gavin/Document'
>>> os.path.expanduser('/usr/lib')
'/usr/lib'

规范路径

os.path.normpath(path) 通过折叠冗余分隔符和上级引用来规范化路径名。

>>> os.path.normpath('/usr//lib//')
'/usr/lib'
>>> os.path.normpath('////usr/lib/')
'/usr/lib'

os.path.abspath(path) 返回一个标准的绝对路径名。

>>> os.path.abspath('./')
'/usr/lib'

>>> os.path.abspath('./python3')
'/usr/lib/python3'

文件时间

除了处理文件路径,os.path 还包含了一些用于检索文件属性的函数。

os.path.getatime(path) 返回 path 的最后访问时间。返回值是一个数字,表示自纪元以来的秒数(参见time模块)。如果文件不存在或无法访问,则引发 OSError。

>>> os.path.getatime('/usr/lib')
1552996323.36275
>>> os.path.getatime('/mnt')
1552224407.037561

os.path.getmtime(path) 返回 path 的最后修改时间。返回值是一个数字,表示自纪元以来的秒数(参见 time 模块)。如果文件不存在或无法访问,则引发 OSError。

>>> os.path.getmtime('/usr/lib')
1552309861.3857274
>>> os.path.getmtime('/mnt')
1532487836.0

os.path.getctime(path) 返回 path 的创建时间。返回值是一个数字,表示自纪元以来的秒数(参见时间模块)。如果文件不存在或无法访问,则引发 OSError。

>>> os.path.getctime('/mnt')
1546701154.282817
>>> os.path.getctime('/usr/lib')
1552309861.3857274

os.path.getsize(path) 返回 path 的大小,以字节为单位。如果文件不存在或无法访问,则引发 OSError。

>>> os.path.getsize('/usr/lib')
4096
>>> os.path.getsize('/usr/lib/python3.6')
20480

检测文件

当一个程序中遇到一个路径名称时,经常需要知道这个路径是指一个文件,目录,系统链接或者它是否存在。

os.path.isabs(path) 如果路径是绝对路径名,则返回 True。

>>> os.path.isabs('./')
False
>>> os.path.isabs('/usr/lib/')
True

os.path.isfile(path) 如果路径是现有的常规文件,则返回 True。这遵循符号链接(软链接),因此 islink() 和 isfile() 对于同一路径可以为 True。

>>> os.path.isfile('./')
False
>>> os.path.isfile('/usr/lib/')
False
>>> os.path.isfile('/home/gavin/Downloads/01.jpg')
True

os.path.isdir(path) 如果文件是目录,则返回 True。这遵循符号链接,因此 islink() 和 isdir() 对于同一路径可以为 True。

>>> os.path.isdir('./')
True
>>> os.path.isdir('/usr/lib/')
True
>>> os.path.isdir('/home/gavin/Downloads/01.jpg')
False

os.path.islink(path) 如果路径指的是符号链接的目录条目,则返回 True。始终 False 如果 Python 运行时不支持符号链接。

gavin@lib$ ls -l
lrwxrwxrwx  1 root root      15 Jan 16  2018 libchm.so.1 -> libchm.so.1.0.0
-rw-r--r--  1 root root   26464 Jan 16  2018 libchm.so.1.0.0

>>> os.path.islink('/usr/lib/libchm.so.1')
True
>>> os.path.islink('/usr/lib/libchm.so.1.0.0')
False

其它

os.path.realpath(path) 返回指定的文件名的规范名字,并消除路径中遇到的任何符号链接(如果操作系统支持的话)。

>>> os.path.realpath('/usr/lib/')
'/usr/lib'
>>> os.path.realpath('/home/gavin/Downloads/01.jpg')
'/home/gavin/Downloads/01.jpg'
>>> os.path.realpath('/usr/lib/libchm.so.1')
'/usr/lib/libchm.so.1.0.0'

os.path.relpath(path, start=os.curdir) 返回自当前目录或者可选的 start 目录到 path 的相对文件路径。

>>> os.path.relpath('/home/gavin/Document')
'../../home/gavin/Document'
>>> os.path.relpath('/home/gavin/Document', '/mnt')
'../home/gavin/Document'

os.path.samefile(path1, path2) 如果两个路径名参数都指向相同的文件或目录,则返回 True。这由设备号和 i 节点号决定,如果对任一路径名的 os.stat() 调用失败,则引发异常。

>>> os.path.samefile('/usr/lib/python3',  'python3')
True
>>> os.path.samefile('/usr/lib/python3',  'python3.6')
False

os.path.sameopenfile(fp1, fp2) 如果文件描述器 fp1 和 fp2 指向同一文件,则返回 True。

os.path.samestat(stat1, stat2) 如果统计数据元组 stat1 和 stat2 指向同一文件,则返回 True。

os.path.splitdrive(path) 将路径名路径拆分为(drive, tail)其中 drive 为挂载点或空字符串。在没有使用驱动器描述符的系统上,drive 将永远是空字符串。

>>> os.path.splitdrive('/usr/lib/python3.6/')
('', '/usr/lib/python3.6/')
>>> os.path.splitdrive('/usr/lib/python3.6')
('', '/usr/lib/python3.6')