os.path——文件名的平台无关操作

来源:互联网 发布:h323视频会议协议端口 编辑:程序博客网 时间:2024/05/23 11:51

原文地址:https://pymotw.com/3/os.path/index.html

目的:文件名与路径的解析,构造,测试和其它工作。

使用os.path模块中的函数在多个平台上操作文件很容易。即使不想在平台之间移植的程序也应该使用os.path进行可靠的文件名解析。

1、解析路径

os.path模块中的第一组函数用于将表示文件名的字符串解析为它们的组成部分。重要的是要意识到,这些函数不依赖于实际存在的路径;它们仅仅是在字符串上操作。

路径解析依赖于在os模块中定义的几个变量:

  • os.sep——路径组成部分之间的分隔符(比如“/”或“\”)。
  • os.extsep——文件名和文件扩展名之间的分隔符(比如“.”)。
  • os.pardir——路径组成部分,表示遍历到目录树的上一层(比如“..”)。
  • os.curdir——路径组成部分,指向当前目录(比如“.”)。

split()函数把路径分割为两个部分,并返回包括结果的一个元组。元组的第二个元素是路径的最后一个组成部分,第一个元素是它之前的所有部分。

# ospath_split.pyimport os.pathPATHS = [    '/one/two/three',    '/one/two/three/',    '/',    '.',    '',]for path in PATHS:    print('{!r:>17} : {}'.format(path, os.path.split(path)))

当输入参数以os.sep结尾,路径的最后一个元素是一个空字符串。

$ python3 ospath_split.py '/one/two/three' : ('/one/two', 'three')'/one/two/three/' : ('/one/two/three', '')              '/' : ('/', '')              '.' : ('', '.')               '' : ('', '')

basename()函数的返回值与split()返回值的第二部分相等

# ospath_basename.pyimport os.pathPATHS = [    '/one/two/three',    '/one/two/three/',    '/',    '.',    '',]for path in PATHS:    print('{!r:>17} : {!r}'.format(path, os.path.basename(path)))

无论指向一个文件还是目录,完整路径都只剩下最后一个元素。如果路径以目录分隔符(os.sep)结尾,那么基础部分认为是空的。

$ python3 ospath_basename.py '/one/two/three' : 'three''/one/two/three/' : ''              '/' : ''              '.' : '.'               '' : ''

dirname()函数返回分割路径的第一部分:

# ospath_dirname.pyimport os.pathPATHS = [    '/one/two/three',    '/one/two/three/',    '/',    '.',    '',]for path in PATHS:    print('{!r:>17} : {!r}'.format(path, os.path.dirname(path)))

组合basename()dirname()的结果会得到原始路径。

$ python3 ospath_dirname.py '/one/two/three' : '/one/two''/one/two/three/' : '/one/two/three'              '/' : '/'              '.' : ''               '' : ''

splitext()split()类似,但它根据扩展名分割,而不是目录分隔符划分路径。

import os.pathPATHS = [    '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)))

查找扩展名时,只会使用最后一次出现的os.extsep,所以如果文件名有多个扩展名,则分割的结果会把部分扩展名留在前缀部分。

$ python3 ospath_splitext.py       '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', '.')

commonprefix()函数接收一个路径列表作为参数,并返回单个字符串,表示所有路径中共有的前缀。这个值可能表示一个不存在的路径,并且路径分隔符不再考虑范围内,所以前缀可能不会再分隔符边界停止。

# ospath_commonprefix.pyimport os.pathpaths = ['/one/two/three/four',         '/one/two/threefold',         '/one/two/three/',         ]for path in paths:    print('PATH:', path)print()print('PREFIX:', os.path.commonprefix(paths))

在这里示例中,尽管有一个路径不包括three目录,但共有前缀字符串是/one/two/three

$ python3 ospath_commonprefix.pyPATH: /one/two/three/fourPATH: /one/two/threefoldPATH: /one/two/three/PREFIX: /one/two/three

commonpath()考虑了路径分隔符,返回不包括部分路径值的前缀。

# ospath_commonpath.pyimport os.pathpaths = [    '/one/two/three/four',    '/one/two/threefold',    '/one/two/three/',]for path in paths:    print('PATH:', path)print()print('PREFIX:', os.path.commonpath(paths))

因为threefoldthree后面没有路径分隔符,所以共有前缀是/one/two

$ python3 ospath_commonpath.pyPATH: /one/two/three/fourPATH: /one/two/threefoldPATH: /one/two/three/PREFIX: /one/two

2、构建路径

除了将现有路径分割,还经常需要从字符串构建路径。使用join()把几个路径部分组合为单个字符串:

# ospath_join.pyimport os.pathPATHS = [    ('one', 'two', 'three'),    ('/', 'one', 'two', 'three'),    ('/one', '/two', '/three'),]for parts in PATHS:    print('{} : {!r}'.format(parts, os.path.join(*parts)))

如果组合的任何参数以os.sep开头,则之前的所有参数都会被丢弃,新的参数成为返回值的开头。

$ python3 ospath_join.py('one', 'two', 'three') : 'one/two/three'('/', 'one', 'two', 'three') : '/one/two/three'('/one', '/two', '/three') : '/three'

还可以使用包含可自动扩展的“可变”组件的路径。例如,expanduser()把波浪符(~)转换为用户主目录的名称。

# ospath_expanduser.pyimport os.pathfor user in ['', 'dhellmann', 'nosuchuser']:    lookup = '~' + user    print('{!r:>15} : {!r}'.format(        lookup, os.path.expanduser(lookup)    ))

如果找不到用户的主目录,则返回未修改的字符串,比如这个示例中的~nosuchuser

$ python3 ospath_expanduser.py            '~' : '/Users/dhellmann'   '~dhellmann' : '/Users/dhellmann'  '~nosuchuser' : '~nosuchuser'

expandvars()更通用,可以扩展路径中出现的任何shell环境变量。

# ospath_expandvars.pyimport os.pathimport osos.environ['MYVAR'] = 'VALUE'print(os.path.expandvars('/path/to/$MYVAR'))

不会执行验证来确保变量值导致已经存在的文件的名称。

$ python3 ospath_expandvars.py/path/to/VALUE

3、规范路径

使用jion()或者嵌入变量,从独立的字符串组合路径可能会带来额外的分隔符或相对路径组件。使用normpath()清理它们:

# ospath_normpath.pyimport os.pathPATHS = [    'one//two//three',    'one/./two/./three',    'one/../alt/two/three',]for path in PATHS:    print('{!r:>22} : {!r}'.format(        path, os.path.normpath(path)    ))

os.curdiros.pardir组成的路径段被计算和折叠了。

$ python3 ospath_normpath.py     'one//two//three' : 'one/two/three'   'one/./two/./three' : 'one/two/three''one/../alt/two/three' : 'alt/two/three'

使用abspath()把相对路径转换为绝对路径。

# ospath_abspath.pyimport os.pathimport osos.chdir('/usr')PATHS = [    '.',    '..',    './one/two/three',    '../one/two/three',]for path in PATHS:    print('{!r:>21} : {!r}'.format(        path, os.path.abspath(path)    ))

结果是完整的路径,从文件系统树的顶部开始。

$ python3 ospath_abspath.py                  '.' : '/usr'                 '..' : '/'    './one/two/three' : '/usr/one/two/three'   '../one/two/three' : '/one/two/three'

4、文件时间

除了使用路径,os.path还包括查询文件属性的函数,类似于os.stat()返回的文件属性:

# ospath_properties.pyimport os.pathimport timeprint('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__))

os.path.getatime()返回访问时间,os.path.getmtime()返回修改时间,os.path.getctime()返回创建时间。os.path.getsize()返回文件中的数据量,以字节表示。

$ python3 ospath_properties.pyFile         : ospath_properties.pyAccess time  : Fri Aug 26 16:38:05 2016Modified time: Fri Aug 26 15:50:48 2016Change time  : Fri Aug 26 15:50:49 2016Size         : 481

5、测试文件

当程序遇到路径名时,通常需要知道路径指向文件,目录还是符号链接,以及它是否存在。os.path包括测试这些所有条件的函数。

# ospath_test.pyimport os.pathFILENAMES = [    __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()

所有的测试函数都返回布尔值。

$ ln -s /does/not/exist broken_link$ python3 ospath_tests.pyFile        : 'ospath_tests.py'Absolute    : FalseIs File?    : TrueIs Dir?     : FalseIs Link?    : FalseMountpoint? : FalseExists?     : TrueLink Exists?: TrueFile        : ''Absolute    : FalseIs File?    : FalseIs Dir?     : FalseIs Link?    : FalseMountpoint? : FalseExists?     : FalseLink Exists?: FalseFile        : '/'Absolute    : TrueIs File?    : FalseIs Dir?     : TrueIs Link?    : FalseMountpoint? : TrueExists?     : TrueLink Exists?: TrueFile        : './broken_link'Absolute    : FalseIs File?    : FalseIs Dir?     : FalseIs Link?    : TrueMountpoint? : FalseExists?     : FalseLink Exists?: True

参考

  • os的标准库文档
  • os.path的Python2到3的移植笔记
  • pathlib —— 路径作为对象。
  • os —— os.path的父模块。
  • time —— time模块包括在os.path中的时间属性函数和易于读取的字符串之间进行转换的函数。
原创粉丝点击