os.path
我们可以利用os.path模块提供的函数更容易地在跨平台上处理文件. 即使我们的程序不是用于夸平台, 也应该使用os.path来让路径名字更加可靠.
Parsing Paths
os.path中的第一个函数集可以用于解析文件名字符串为不同部分. 要注意到这些函数的解析不依赖于被解析的路径是否真正存在, 他们只处理字符串.
路径解析依赖于一些os实现定义好的变量, 如:
- os.sep : 表示路径的分隔符(如, “/”).
- os.extsep : 表示文件名和文件扩展名的分隔符(如, “.”).
- os.pardir : 表示上一层目录, 即父目录(如, “..”).
- os.curdir :表示当前目录(如, “.”)。
os.path.split(path):将路径名路径拆分为一对(头、尾),其中尾是最后的路径名组件,头是所有的一切。 尾部分不会包含斜杠;如果路径以斜线结尾,则尾将为空。如果path中没有斜线,head将为空。如果path为空,head 和 tail两个都将为空。尾部的斜线会从head中去除掉,除非它是根目录(只包含一个或多个斜线的目录)。在所有情况下,join(head, tail)返回与path相同位置的路径字符串可能不同)。
os.path.basename(path):返回 path 路径名的基的名称。这是通过将path参数传递给 split()函数返回的第二个元素。
os.path.dirname(path):返回 path中的目录名.实际上是通过将path参数传递个 split()函数得到的返回值的第一个元素.
os.path.splitext(path):Split the pathname path into a pair (root, ext) such that root + ext == path, and ext is empty or begins with a period and contains at most one period. 忽略基本名称上的前导周期; splitext('.cshrc')返回('。cshrc', '')。
os.path.commonprefix(list):返回列表中所有路径的前缀的最长路径前缀(逐个字符)。如果列表为空,则返回空字符串('')。
os.path.commonpath(paths):返回 paths参数中,所有路径序列*有的最长的路径.如果 paths 即包含绝对路径又包含相对路径,或者 paths 为空将抛出ValueError.不同于 commonprefix()函数, commonpath()返回一个有效的路径.
举例
split() 函数将路径切分成两个两部分并返回一个元组, 它的第二个元素是路径的最后一部份, 第一个元素是路径的前面部分.
PATHS = ['/one/two/three', '/one/two/three/', '/', ',', '',]
for path in PATHS:
print('{!r:>17} : {}'.format(path, os.path.split(path)))
输出:
'/one/two/three' : ('/one/two', 'three')
'/one/two/three/' : ('/one/two/three', '')
'/' : ('/', '')
',' : ('', ',')
'' : ('', '')
basename() 返回的值和 split() 返回的第二个值相同.
PATHS = ['/one/two/three', '/one/two/three/', '/', ',', '',]
for path in PATHS:
print(' {!r:>17} : {!r}'.format(path, os.path.basename(path)))
输出:
'/one/two/three' : 'three'
'/one/two/three/' : ''
'/' : ''
',' : ','
'' : ''
dirname() 返回的值是和 split() 返回的第一个值相同.
PATHS = ['/one/two/three', '/one/two/three/', '/', ',', '',]
for path in PATHS:
print(' {!r:>17} : {!r}'.format(path, os.path.dirname(path)))
输出:
'/one/two/three' : '/one/two'
'/one/two/three/' : '/one/two/three'
'/' : '/'
',' : ''
'' : ''
splitext() 和 split() 类似但是分隔路径的扩展名, 而不是目录名.
PATHS = ['filename.txt', 'filename', '/path/to/filename.txt', '/', '', 'my-archive.tar.gz', 'no-extension.', ]
for path in PATHS:
print(' {!r:>21} : {!r}'.format(path, os.path.splitext(path)))
输出:
'filename.txt' : ('filename', '.txt')
'filename' : ('filename', '')
'/path/to/filename.txt' : ('/path/to/filename', '.txt')
'/' : ('/', '')
'' : ('', '')
'my-archive.tar.gz' : ('my-archive.tar', '.gz')
'no-extension.' : ('no-extension', '.')
在寻找扩展名时,只使用最后一次出现的os.extsep,所以如果一个文件名有多个扩展名,则分割结果会使前缀部分扩展名。
commonprefix() 取一个路径列表作为参数, 返回一个单一的字符串表示这些路径公共的前缀. 这个值可能是一个实际上不存在的路径. 路径分割符是被忽略的, 所以前缀可能在在分割处被截断.
paths = ['/one/two/three/four', '/one/two/threefold', '/one/two/three', ]
for path in paths:
print('PATH:', path)
print()
print('PREFIX:', os.path.commonprefix(paths))
输出:
PATH: /one/two/three/four
PATH: /one/two/threefold
PATH: /one/two/three
PREFIX: /one/two/three
commonpath() does honor path separators, and returns a prefix that does not include partial path values.
paths = ['/one/two/three/four', '/one/two/threefold', '/one/two/three/', ]
for path in paths:
print('PATH:', path)
print()
print('PREGIX:', os.path.commonpath(paths))
Linux 输出:
PATH: /one/two/three/four
PATH: /one/two/threefold
PATH: /one/two/three/
PREGIX: /one/two
Building Paths
除了将现有的路径分隔外, 你可能经常会将多个字符串组合成一个路径.可以使用 join() 将多个路径部分组合成一个单个值:
os.path.join(path, *paths):将一个或多个路径正确地连接起来。返回值是路径和*路径的任何成员与每个非空的后面紧跟一个目录分隔符(os.sep)的连接部分,除了最后一个,意味着结果将只在分隔符结束,如果最后一部分为空。如果组件是绝对路径,则所有先前组件都将被丢弃,并且从绝对路径组件继续加入。
os.path.expanduser(path):在Unix和Windows上,返回以或user为起始组件的参数替换为用户的主目录。在Unix上,如果设置了初始~,则替换为环境变量 HOME否则通过内建模块pwd在密码目录中查找当前用户的主目录。在密码目录中直接查找初始~user。在Windows上,如果设置,将使用 HOME和 USERPROFILE,否则 t6 > HOMEPATH和 HOMEDRIVE。通过从上面得到的创建的用户路径剥离最后一个目录组件来处理初始user。如果扩展失败或者参数path不是以打头,则直接返回参数(path)。
os.path.expandvars(path):返回参数,其中的环境变量被扩展。形式$name或${name}的子字符串由环境变量name的值替换。如果格式不正确或者引用了不存在的变量,则不进行替换(或者扩展)。在Windows上,除了$name和${name}之外,还支持%name%扩展。
举例
PATHS = [('one', 'two', 'three'), ('/', 'one', 'two', 'three'), ('/one', '/two', '/three'), ]
for parts in PATHS:
print(' {} : {!r}'.format(parts, os.path.join(*parts)))
Linux输出:
('one', 'two', 'three') : 'one/two/three'
('/', 'one', 'two', 'three') : '/one/two/three'
('/one', '/two', '/three') : '/three'
如果路径中包含变量部分, 也能自动将她扩展出来. 例如, expanduser() 可以将波浪线(~)扩展成用户的主目录.
for user in ['', 'dhellmann', 'nosuchuser']:
lookup = '~' + user
print(' {!r:>15} : {!r}'.format(lookup, os.path.expanduser(lookup)))
Linux输出:
'~' : '/root'
'~/dhellmann' : '/root/dhellmann'
'~/nosuchuser' : '/root/nosuchuser'
expandvars() 是能更一般的扩展出现在路径中的环境变量.
import os.path
import os
os.environ['MYVAR'] = 'VALUE'
print(os.path.expandvars('/path/to/$MYVAR'))
Linux输出:
/path/to/VALUE
Normalizing Paths
os.path.normpath(path):通过折叠冗余分隔符和上级引用来归一化路径名,以使A//B,A/B/,A/./B和A/foo/../B都变为A/B。该字符串操作可能改变包含符号链接的路径的含义。在Windows上,还会将斜线转换成反斜线。要规范化情况,请使用normcase()。
os.path.abspath(path):返回一个标准的绝对路径名 path.在大多数平台上,该函数等效于调用 normpath()函数, 如下所示: normpath(join(os.getcwd(), path)).
举例
使用 join() 组装成的, 或嵌入了变量的Paths路径可能会以多余的分隔符结束或含有相对路径部份. 使用 normpath() 将这些清除:
PATHS = ['one//two//three', 'one/./two/./three', 'one/../alt/two/three', ]
for path in PATHS:
print(' {!r:>22} : {!r}'.format(path, os.path.normpath(path)))
Linux输出:
'one//two//three' : 'one/two/three'
'one/./two/./three' : 'one/two/three'
'one/../alt/two/three' : 'alt/two/three'
使用 abspath() 将一个相对路径转换成绝对路径.
import os
import os.path
os.chdir('/usr')
PATHS = ['.', '..', './one/two/three', '../one/two/three', ]
for path in PATHS:
print(' {!r:>21} : {!r}'.format(path, os.path.abspath(path)))
Linux输出:
'.' : '/usr'
'..' : '/'
'./one/two/three' : '/usr/one/two/three'
'../one/two/three' : '/one/two/three'
File Times
os.path.getatime(path):返回 path的上次访问时间.返回值是一个数字,表示自纪元以来的秒数(参见time模块)。如果文件不存在或无法访问,则引发OSError。如果os.stat_float_times()返回True,则结果为浮点数。
os.path.getmtime(path):返回path的最后修改时间。返回值是一个数字,表示自纪元以来的秒数(参见time模块)。如果文件不存在或无法访问,则引发OSError。如果os.stat_float_times()返回True,则结果为浮点数。
os.path.getctime(path):返回系统的ctime,在某些系统(如Unix)上是最后元数据更改的时间,在其他系统(如Windows)上,是路径的创建时间。返回值是一个数字,表示自纪元以来的秒数(参见时间模块)。如果文件不存在或无法访问,则引发OSError。
os.path.getsize(path):返回path的大小,以字节为单位。如果文件不存在或无法访问,则引发OSError。
举例
除了处理路径外, os.path 还可以包含一些用于检索文件属性的函数, 他们比 os.stat() 更方便:
import os.path
import time
print('File :', __file__)
print('Access time :', time.ctime(os.path.getatime(__file__)))
print('Modified time:', time.ctime(os.path.getmtime(__file__)))
print('Change time :', time.ctime(os.path.getctime(__file__)))
print('Size :', os.path.getsize(__file__))
Linux输出:
File : os_path_study.py
Access time : Wed Jul 5 23:21:48 2017
Modified time: Wed Jul 5 23:21:46 2017
Change time : Wed Jul 5 23:21:46 2017
Size : 314
Testing Files
os.path.isabs(path):如果路径是绝对路径名,则返回True。在Unix上,这表示路径以/开始;在Windows上,这表示路径以\开始(在去掉可能的盘符后,如C:)。
os.path.isfile(path):如果路径是现有的常规文件,则返回True。这遵循符号链接(软链接),因此islink()和isfile()对于同一路径可以为true。
os.path.isdir(path):如果文件是目录,则返回True。这遵循符号链接,因此islink()和isdir()对于同一路径可以为true。
os.path.islink(path):如果路径指的是符号链接的目录条目,则返回True。始终False如果Python运行时不支持符号链接。
os.path.ismount(path):如果路径名路径是安装点,则返回TrueOn POSIX, the function checks whether path‘s parent, path/.., is on a different device than path, or whether path/.. and path point to the same i-node on the same device — this should detect mount points for all Unix and POSIX variants. 在Windows上,驱动器号根和共享UNC始终是安装点,并且调用任何其他路径GetVolumePathName以查看它是否与输入路径不同。版本3.4中的新功能:支持在Windows上检测非根安装点。
os.path.exists(path):如果路径指向现有路径或打开的文件描述器,则返回True。如果是损坏的符号链接,则返回False.在某些平台上,如果未授予在所请求的文件上执行os.stat()的权限,此函数可能会返回False,即使路径物理上确实是存在的。版本 3.3 中的更改︰现在,path 可以是一个整数︰ 返回 True 如果它是一个打开的文件描述符,否则为False。
os.path.lexists(path):如果 path 指向现有的路径,则返回 True。破碎的符号链接将返回 True。在缺少os.lstat()的平台上等效于exists()。
举例
当你的程序含一个路径名时, 他通常需要知道这个路径是否是文件还是目录. 如果你的平台支持它, 你需要知道这个路径是指向一个符号链接还是是一个挂载点. 你也可能想测试路径是否存在. os.path 提供测试这些条件的函数.
FILENAMES = [__file__, os.path.dirname(__file__), '/', './broken_link', ]
for file in FILENAMES:
print('File : {!r}'.format(file))
print('Absolute :', os.path.isabs(file))
print('Is File? :', os.path.isfile(file))
print('Is Dir? :', os.path.isdir(file))
print('Is Link? :', os.path.islink(file))
print('Mountpoint? :', os.path.ismount(file))
print('Exists? :', os.path.exists(file))
print('Link Exists? :', os.path.lexists(file))
print()
Linux输出:
File : 'os_path_study.py'
Absolute : False
Is File? : True
Is Dir? : False
Is Link? : False
Mountpoint? : False
Exists? : True
Link Exists? : True
File : ''
Absolute : False
Is File? : False
Is Dir? : False
Is Link? : False
Mountpoint? : False
Exists? : False
Link Exists? : False
File : '/'
Absolute : True
Is File? : False
Is Dir? : True
Is Link? : False
Mountpoint? : True
Exists? : True
Link Exists? : True
File : './broken_link'
Absolute : False
Is File? : False
Is Dir? : False
Is Link? : False
Mountpoint? : False
Exists? : False
Link Exists? : False