本文基于 Python3 編寫測(cè)試。
os.path 模塊是跨平臺(tái)的,即使不打算在平臺(tái)之間移植自己的程序也應(yīng)該用 os.path,好處多多。
解析路徑
第一組 os.path 函數(shù)可用于將表示文件名的字符串解析為其組成部分。重要的是要意識(shí)到這些功能不依賴于實(shí)際存在的路徑。
路徑解析取決于以下定義的一些 os 變量:
-
os.sep- 路徑部分之間的分隔符(例如,“/”或“\”)。 -
os.extsep- 文件名和文件“擴(kuò)展名”之間的分隔符(例如,“.”)。 -
os.pardir- 路徑組件,意味著將目錄樹向上遍歷一級(jí)(例如,“..”)。 -
os.curdir- 引用當(dāng)前目錄的路徑組件(例如,“.”)。
split() 函數(shù)將路徑分成兩個(gè)獨(dú)立的部分,并返回一個(gè)tuple結(jié)果。第二個(gè)元素是路徑的最后一個(gè)元素,第一個(gè)元素是它之前的所有元素。
import os.path
PATHS = [
'/one/two/three',
'/one/two/three/',
'/',
'.',
'',
]
for path in PATHS:
print('{!r:>17} : {}'.format(path, os.path.split(path)))
# output
# '/one/two/three' : ('/one/two', 'three')
# '/one/two/three/' : ('/one/two/three', '')
# '/' : ('/', '')
# '.' : ('', '.')
# '' : ('', '')
當(dāng)輸入?yún)?shù)以 os.sep 結(jié)束時(shí),路徑的最后一個(gè)元素是一個(gè)空字符串。
basename()函數(shù)返回一個(gè)等于 split() 返回值的第二部分的值。
import os.path
PATHS = [
'/one/two/three',
'/one/two/three/',
'/',
'.',
'',
]
for path in PATHS:
print('{!r:>17} : {!r}'.format(path, os.path.basename(path)))
# output
# '/one/two/three' : 'three'
# '/one/two/three/' : ''
# '/' : ''
# '.' : '.'
# '' : ''
完整路徑被剝離到最后一個(gè)元素,無論是指文件還是目錄。
dirname()函數(shù)返回拆分路徑的第一部分:
import os.path
PATHS = [
'/one/two/three',
'/one/two/three/',
'/',
'.',
'',
]
for path in PATHS:
print('{!r:>17} : {!r}'.format(path, os.path.dirname(path)))
# output
# '/one/two/three' : '/one/two'
# '/one/two/three/' : '/one/two/three'
# '/' : '/'
# '.' : ''
# '' : ''
結(jié)合basename() 和 dirname() 的結(jié)果可以返回原始路徑。
splitext()類似于split(),但在擴(kuò)展分隔符上劃分路徑,而不是目錄分隔符。
import os.path
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)))
# output
# '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在查找擴(kuò)展名時(shí)僅匹配最后一次出現(xiàn)的分隔符,因此如果文件名具有多個(gè)擴(kuò)展名,則會(huì)按照最后一個(gè)擴(kuò)展名進(jìn)行拆分。
commonprefix()將路徑列表作為參數(shù),并返回表示所有路徑中存在的公共前綴的單個(gè)字符串。該值還可以表示實(shí)際上不存在的路徑,并且路徑分隔符不包括在考慮中。
import os.path
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))
# output
# PATH: /one/two/three/four
# PATH: /one/two/threefold
# PATH: /one/two/three/
#
# PREFIX: /one/two/three
在此示例中,公共前綴字符串是/one/two/three,即使一個(gè)路徑不包含名為的目錄three。
commonpath() 考慮路徑分隔符,并返回不包含部分路徑值的前綴。
import os.path
paths = ['/one/two/three/four',
'/one/two/threefold',
'/one/two/three/',
]
for path in paths:
print('PATH:', path)
print()
print('PREFIX:', os.path.commonpath(paths))
# output
# PATH: /one/two/three/four
# PATH: /one/two/threefold
# PATH: /one/two/three/
#
# PREFIX: /one/two
構(gòu)建路徑
除了將現(xiàn)有路徑分開之外,經(jīng)常需要從其他字符串構(gòu)建路徑。要將多個(gè)路徑組合為單個(gè)值,可以使用join():
import os.path
PATHS = [
('one', 'two', 'three'),
('/', 'one', 'two', 'three'),
('/one', '/two', '/three'),
]
for parts in PATHS:
print('{} : {!r}'.format(parts, os.path.join(*parts)))
# output
# ('one', 'two', 'three') : 'one/two/three'
# ('/', 'one', 'two', 'three') : '/one/two/three'
# ('/one', '/two', '/three') : '/three'
如果有任何一個(gè)參數(shù)是以 os.sep 開頭的,則先前所有的參數(shù)都會(huì)被丟棄,并將該值作為返回值的開頭。
也可以使用包含可以自動(dòng)擴(kuò)展的“可變”組件的路徑。例如,expanduser() 將 ~ 字符轉(zhuǎn)換為用戶主目錄的名稱。
import os.path
for user in ['', 'dhellmann', 'nosuchuser']:
lookup = '~' + user
print('{!r:>15} : {!r}'.format(lookup, os.path.expanduser(lookup)))
# output
# '~' : '/Users/dhellmann'
# '~dhellmann' : '/Users/dhellmann'
# '~nosuchuser' : '~nosuchuser'
如果找不到用戶的主目錄,則返回字符串不變,如~nosuchuser。
expandvars() 更通用,擴(kuò)展路徑中存在的任何 shell 環(huán)境變量。
import os.path
import os
os.environ['MYVAR'] = 'VALUE'
print(os.path.expandvars('/path/to/$MYVAR')) # /path/to/VALUE
并不會(huì)驗(yàn)證文件或路徑是否存在。
規(guī)范化路徑
使用join() 組合的路徑可能會(huì)有額外的分隔符或相對(duì)路徑。用 normpath()來清理它們:
import os.path
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)))
# output
# 'one//two//three' : 'one/two/three'
# 'one/./two/./three' : 'one/two/three'
# 'one/../alt/two/three' : 'alt/two/three'
要將相對(duì)路徑轉(zhuǎn)換為絕對(duì)文件名,請(qǐng)使用 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)))
# output
# '.' : '/usr'
# '..' : '/'
# './one/two/three' : '/usr/one/two/three'
# '../one/two/three' : '/one/two/three'
文件時(shí)間
除了使用路徑之外,os.path還包括用于檢索文件屬性的函數(shù),類似于 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__))
# output
# File : ospath_properties.py
# Access time : Sun Mar 18 16:21:22 2018
# Modified time: Fri Nov 11 17:18:44 2016
# Change time : Fri Nov 11 17:18:44 2016
# Size : 481
os.path.getatime()返回訪問時(shí)間, os.path.getmtime()返回修改時(shí)間,os.path.getctime()返回創(chuàng)建時(shí)間。 os.path.getsize()返回文件中的數(shù)據(jù)量,以字節(jié)為單位表示。
測(cè)試文件
當(dāng)程序遇到路徑名時(shí),通常需要知道路徑是指文件,目錄還是符號(hào)鏈接以及它是否存在。 os.path包括測(cè)試所有這些條件的功能。
import 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()
# output
# File : 'ospath_tests.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? : True
# Mountpoint? : False
# Exists? : False
# Link Exists?: True
所有測(cè)試函數(shù)都返回布爾值。
相關(guān)文檔: