Table Of Contents

Previous topic

PyMOTW: urlparse

Next topic

PyMOTW: time

This Page

PyMOTW: os.path

  • 模块:os.path
  • 目的:对文件名和路径进行解析, 创建, 测试和其他操作.
  • python版本:1.4+

描述

我们可以利用os.path模块提供的函数更容易地在跨平台上处理文件. 即使我们的程序不是用于夸平台, 也应该使用os.path来让路径名字更加可靠.

解析路径

os.path中的第一个函数集可以用于解析文件名字符串为不同部分. 要注意到这些函数的解析不依赖于被解析的路径是否真正存在, 他们只处理字符串.

路径解析依赖于一些os实现定义好的变量, 如:

  • os.sep : 表示路径的分隔符(如, “/”).
  • os.extsep : 表示文件名和文件扩展名的分隔符(如, ”.”).
  • os.pardir : 表示上一层目录, 即父目录(如, ”..”).
  • os.curdir :表示当前目录(如, ”.”)。

split() 函数将路径切分成两个两部分并返回一个元组, 它的第二个元素是路径的最后一部份, 第一个元素是路径的前面部分.

import os.path

for path in [ '/one/two/three','/one/two/three/','/',',']:
    print '"%s" : "%s"' % (path, os.path.split(path))
$ python ospath_split.py
"/one/two/three" : "('/one/two', 'three')"
"/one/two/three/" : "('/one/two/three', '')"
"/" : "('/', '')"
"." : "('', '.')"
"" : "('', '')"

basename() 返回的值和 split() 返回的第二个值相同.

import os.path

for path in [ '/one/two/three','/one/two/three/','/','.','']:
    print '"%s" : "%s"' % (path, os.path.basename(path))
$ python ospath_basename.py
"/one/two/three" : "three"
"/one/two/three/" : ""
"/" : ""
"." : "."
"" : ""

dirname() 返回的值是和 split() 返回的第一个值相同.

import os.path

for path in [ '/one/two/three', '/one/two/three/','/','.','']:
    print '"%s" : "%s"' % (path, os.path.dirname(path))
$ python ospath_dirname.py

"/one/two/three" : "/one/two"
"/one/two/three/" : "/one/two/three"
"/" : "/"
"." : ""
"" : ""

splitext()split() 类似但是分隔路径的扩展名, 而不是目录名.

import os.path

for path in [ 'filename.txt', 'filename', '/path/to/filename.txt', '/', '' ]:
    print '"%s" :' % path, os.path.splitext(path)
$ python ospath_splitext.py
"filename.txt" : ('filename', '.txt')
"filename" : ('filename', '')
"/path/to/filename.txt" : ('/path/to/filename', '.txt')
"/" : ('/', '')
"" : ('', '')

commonprefix() 取一个路径列表作为参数, 返回一个单一的字符串表示这些路径公共的前缀. 这个值可能是一个实际上不存在的路径. 路径分割符是被忽略的, 所以前缀可能在在分割处被截断.

import os.path

paths = ['/one/two/three/four','/one/two/threefold','/one/two/three/',]
print paths
print os.path.commonprefix(paths)
$ python ospath_commonprefix.py
['/one/two/three/four', '/one/two/threefold', '/one/two/three/']
/one/two/three

创建路径

除了将现有的路径分隔外, 你可能经常会将多个字符串组合成一个路径.

可以使用 join() 将多个路径部分组合成一个单个值:

import os.path

for parts in [ ('one', 'two', 'three'),('/', 'one', 'two', 'three'),('/one', '/two', '/three'),]:
    print parts, ':', os.path.join(*parts)
$ python ospath_join.py
('one', 'two', 'three') : one/two/three
('/', 'one', 'two', 'three') : /one/two/three
('/one', '/two', '/three') : /three

如果路径中包含变量部分, 也能自动将她扩展出来. 例如, expanduser() 可以将波浪线(~)扩展成用户的主目录.

import os.path

for user in [ '', 'dhellmann', 'postgres' ]:
    lookup = '~' + user
    print lookup, ':', os.path.expanduser(lookup)
$ python ospath_expanduser.py
~ : /Users/dhellmann
~dhellmann : /Users/dhellmann
~postgres : /var/empty

expandvars() 是能更一般的扩展出现在路径中的环境变量.

import os.path
import os

os.environ['MYVAR'] = 'VALUE'

print os.path.expandvars('/path/to/$MYVAR')
$ python ospath_expandvars.py
/path/to/VALUE

标准化路径

使用 join() 组装成的, 或嵌入了变量的Paths路径可能会以多余的分隔符结束或含有相对路径部份. 使用 normpath() 将这些清除:

import os.path

for path in [ 'one//two//three', 'one/./two/./three', 'one/../one/two/three',]:
    print path, ':', os.path.normpath(path)
$ python ospath_normpath.py
one//two//three : one/two/three
one/./two/./three : one/two/three
one/../one/two/three : one/two/three

使用 abspath() 将一个相对路径转换成绝对路径.

import os.path

for path in [ '.', '..', './one/two/three', '../one/two/three']:
    print '"%s" : "%s"' % (path, os.path.abspath(path))
$ python ospath_abspath.py
"." : "/Users/dhellmann/Documents/PyMOTW/in_progress/ospath"
".." : "/Users/dhellmann/Documents/PyMOTW/in_progress"
"./one/two/three" : "/Users/dhellmann/Documents/PyMOTW/in_progress/ospath/one/two/three"
"../one/two/three" : "/Users/dhellmann/Documents/PyMOTW/in_progress/one/two/three"

文件时间

除了处理路径外, 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__)
$ python ospath_properties.py
File : /Users/dhellmann/Documents/PyMOTW/in_progress/ospath/ospath_properties.py
Access time : Sun Jan 27 15:40:20 2008
Modified time: Sun Jan 27 15:39:06 2008
Change time : Sun Jan 27 15:39:06 2008
Size : 478

测试文件

当你的程序含一个路径名时, 他通常需要知道这个路径是否是文件还是目录. 如果你的平台支持它, 你需要知道这个路径是指向一个符号链接还是是一个挂载点. 你也可能想测试路径是否存在. os.path 提供测试这些条件的函数.

import os.path

for file in [ __file__, os.path.dirname(__file__), '/', './broken_link']:
    print 'File :', 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
$ python ospath_tests.py
File : /Users/dhellmann/Documents/PyMOTW/in_progress/ospath/ospath_tests.py
Absolute : True
Is File? : True
Is Dir? : False
Is Link? : False
Mountpoint? : False
Exists? : True
Link Exists?: True

File : /Users/dhellmann/Documents/PyMOTW/in_progress/ospath
Absolute : True
Is File? : False
Is Dir? : True
Is Link? : False
Mountpoint? : False
Exists? : True
Link Exists?: True

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? : True
Mountpoint? : False
Exists? : False
Link Exists?: True

遍历目录树

os.path.walk() 遍历树中的所有目录, 并调用一个你提供的函数, 同时将目录名和目录中包含内容的名字传递给这个函数. 下面的例子将递归的列出目录, 但忽略.svn目录.

import os.path
import pprint

def visit(arg, dirname, names):
    print dirname, arg
    for name in names:
        subname = os.path.join(dirname, name)
        if os.path.isdir(subname):
            print ' %s/' % name
        else:
            print ' %s' % name
    # Do not recurse into .svn directory
    if '.svn' in names:
        names.remove('.svn')
    print

os.path.walk('..', visit, '(User data)')
$ python ospath_walk.py
.. (User data)
   .svn/
   ospath/

../ospath (User data)
   .svn/
   __init__.py
   ospath_abspath.py
   ospath_basename.py
   ospath_commonprefix.py
   ospath_dirname.py
   ospath_expanduser.py
   ospath_expandvars.py
   ospath_join.py
   ospath_normpath.py
   ospath_properties.py
   ospath_split.py
   ospath_splitext.py
   ospath_tests.py
   ospath_walk.py