1. pathlib檔案系統路徑作為物件
pathlib模塊提供了一個面向物件API來決議、建立、測驗和處理檔案名和路徑,而不是使用底層字串操作,
1.1 路徑表達
pathlib包含一些類來管理使用POSIX標準或Microsoft Windows語法格式化的檔案系統路徑,這個模塊包含一些“純”類,會處理字串但不與實際的檔案系統互動,另外還包含一些“具體”類,它們擴展了API,以包含可以反映或修改本地檔案系統上資料的操作,
純類PurePosixPath和PureWindowsPath可以在任意作業系統上實體化和使用,因為它們只處理檔案名和目錄名,要實體化一個具體類來處理真正的檔案系統,需要使用Path得到一個PosixPath或WindowsPath,這取決于具體的平臺,
1.2 建立路徑
要實體化一個新路徑,可以提供一個字串作為第一個引數,路徑物件的字串表示就是這個名值,要創建一個新路徑來指定相對于已有路徑的一個值,可以使用/運算子擴展這個路徑,這個運算子的引數可以是一個字串,也可以是另一個路徑物件,
import pathlib usr = pathlib.PurePosixPath('/usr') print(usr) usr_local = usr / 'local' print(usr_local) usr_share = usr / pathlib.PurePosixPath('share') print(usr_share) root = usr / '..' print(root) etc = root / '/etc/' print(etc)
如示例輸出中root的值所示,這個運算子會組合所提供的路徑值,但是在包含父目錄參考“..”時沒有對結果進行規范化,不過,如果在一個路徑段以路徑分隔符開頭,那么與os.path.join()中一樣,會把它解釋為一個新的“根”參考,會從路徑值中間洗掉額外的路徑分隔符,如這里的etc示例所示,

具體路徑類包括一個用于規范化路徑resolve()方法,它會在檔案系統中查找目錄和符號鏈接,并生成一個名指示的絕對路徑,
import pathlib usr_local = pathlib.Path('/usr/local') share = usr_local / '..' / 'share' print(share.resolve())
這里相對路徑被轉換為絕對路徑E:\usr\shar,如果輸入路徑包含符號鏈接,那么它們也會展開,以使規范化的路徑直接指示目標,

要想在路徑段提前不可知時建立路徑,可以使用joinpath(),并傳入各個路徑段作為一個單獨的引數,
import pathlib root = pathlib.PurePosixPath('/') subdirs = ['usr', 'local'] usr_local = root.joinpath(*subdirs) print(usr_local)
與/運算子一樣,呼叫joinpath()會創建一個新實體,

給定一個現有的路徑物件,可以很容易地建立一個與它稍有差別的新物件,如指示同一個目錄中的另一個檔案,可以使用with_name()創建一個新路徑,將一個路徑中的部分替換為另一個不同的檔案名,使用with_suffix()也可以創建一個新路徑,將檔案名的擴展名替換為一個不同的值,
import pathlib ind = pathlib.PurePosixPath('source/pathlib/index.rst') print(ind) py = ind.with_name('pathlib_from_existing.py') print(py) pyc = py.with_suffix('.pyc') print(pyc)
這兩個方法都回傳新物件,原來的物件仍保持不變,

1.3 決議路徑
路徑物件提供了一些方法和屬性可以從路徑名中抽取出部分值,例如,parts屬性可以生成根據路徑分隔符決議得到的一個路徑段序列,
路徑物件具有從名稱中提取部分值的方法和屬性,例如,parts屬性可以生成根據路徑分隔符值決議得到的一個路徑段序列,
import pathlib p = pathlib.PurePosixPath('/usr/local') print(p.parts)
這個序列是一個元組,反映了路徑實體的不可變性,

有兩種方法可以從一個給定的路徑物件在檔案系統層次結構中“向上”導航,parent屬性指示一個新的路徑實體,對應包含給定路徑(os.path.dirname()回傳的值)的目錄,parents屬性是一個迭代器,會生成一系列父目錄參考,在路徑層次結構中不斷“向上”,直到到達檔案系統的根目錄,
import pathlib p = pathlib.PurePosixPath('/usr/local/lib') print('parent: {}'.format(p.parent)) print('\nhierarchy:') for up in p.parents: print(up)
這個例子迭代處理parents屬性并列印成員值,

可以通過路徑物件的屬性來訪問路徑的其他部分,Name屬性包含路徑的最后一部分,即最后一個路徑分隔符后面的部分(與os.path.basename()生成的值相同),suffix屬性包含擴展名分隔符后面的值,stem屬性包含名字中后綴之前的部分,
import pathlib p = pathlib.PurePosixPath('./source/pathlib/pathlib_name.py') print('path : {}'.format(p)) print('name : {}'.format(p.name)) print('suffix: {}'.format(p.suffix)) print('stem : {}'.format(p.stem))
盡管suffix和stem的值與os.path.splitext()生成的值類似,但這些值只是基于name的值,而不是完整路徑,

1.4 創建具體路徑
可以由字串引數創建具體Path類的實體,字串引數可能指示檔案系統中一個檔案、目錄或符號鏈接的名字(或可能的名字),這個類還提供了很多便利方法,可以使用常用位置(如當前作業目錄和用戶的主目錄)建立路徑實體,這些常用位置可能會改變,
import pathlib home = pathlib.Path.home() print('home: ', home) cwd = pathlib.Path.cwd() print('cwd : ', cwd)
這兩個方法都會創建預填充一個絕對檔案系統參考的Path實體,

1.5 目錄內容
可以使用3個方法來訪問目錄串列以及發現檔案系統中的檔案名,iterdir()是一個生成器,會為包含目錄中的每個元素生成一個新的path實體,
import pathlib p = pathlib.Path('.') for f in p.iterdir(): print(f)
如果Path不指示一個目錄,則iterdir()會產生NotADirectoryError,

可以使用glob()找出與一個模式匹配的檔案,
import pathlib p = pathlib.Path('..') for f in p.glob('*.py'): print(f)
這個例子展示了腳本父目錄中的所有py檔案,

glob處理器支持使用模式前綴**或者通過呼叫rglob()而不是glob()來完成遞回掃描,
import pathlib p = pathlib.Path('..') for f in p.rglob('*.py'): print(f)
由這個例子從父目錄開始,所以必須通過一個遞回搜索來查找與*.py匹配的示例檔案,

1.6 讀寫檔案
每個Path實體都包含一些方法來處理所指示檔案的內容,要直接獲取內容,可以使用read_bytes()或read_text(),要寫入檔案,可以使用write_bytes()或write_text(),可以使用open()方法打開檔案并保存檔案句柄,而不是向內置的open()函式傳入檔案名,
import pathlib f = pathlib.Path('example.txt') f.write_bytes('This is the content'.encode('utf-8')) with f.open('r', encoding='utf-8') as handle: print('read from open(): {!r}'.format(handle.read())) print('read_text(): {!r}'.format(f.read_text('utf-8')))
這些便利方法會在打開檔案和寫入檔案之前完成一些型別檢查,除此之外,它們與直接操作是等價的,

1.7 管理目錄和符號鏈接
可以用表示不存在的目錄或符號鏈接的路徑來創建關聯的檔案系統項,
import pathlib p = pathlib.Path('example_dir') print('Creating {}'.format(p)) p.mkdir()
如果這個路徑已經存在,則mkdir()會產生一個FileExistsError,


可以使用symlink_to()創建一個符號鏈接,這個鏈接根據路徑的值命名,將指示symlink_to()引數給定的名字,
import pathlib p = pathlib.Path('example_link') p.symlink_to('index.rst') print(p) print(p.resolve().name)
這個例子首先創建一個符號鏈接,然后使用resolve()讀取這個鏈接來找出它指示的名字,并列印這個名字,

1.8 檔案型別
Path實體包含一些方法來檢查路徑指示的檔案的型別,下面這個例子測驗它們,
import pathlib p = pathlib.Path('demo.py') hfmt = '{:18s}' + (' {:>5}' * 6) print(hfmt.format('Name', 'File', 'Dir', 'Link', 'FIFO', 'Block', 'Character')) print() fmt = '{:20s} ' + ('{!r:>5} ' * 6) print(fmt.format( str(p), p.is_file(), p.is_dir(), p.is_symlink(), p.is_fifo(), p.is_block_device(), p.is_char_device(), ))
所有這些方法(is_dir()、is_file()、is_symlink()、is_fifo()、is_block_device()和is_char_device())都不帶引數,

1.9 檔案屬性
可以使用方法stat()和lstat()來訪問檔案的有關詳細資訊(lstat()用于檢查一個可能是符號鏈接的目標的狀態),這些方法生成的結果分別與os.stat()和os.lstat()相同,
import pathlib import sys import time if len(sys.argv) == 1: filename = __file__ else: filename = sys.argv[1] p = pathlib.Path(filename) stat_info = p.stat() print('{}:'.format(filename)) print(' Size:', stat_info.st_size) print(' Permissions:', oct(stat_info.st_mode)) print(' Owner:', stat_info.st_uid) print(' Device:', stat_info.st_dev) print(' Created :', time.ctime(stat_info.st_ctime)) print(' Last modified:', time.ctime(stat_info.st_mtime)) print(' Last accessed:', time.ctime(stat_info.st_atime))
取決于在哪里安裝這個示例代碼,輸出可能有變化,

1.10 洗掉
提供了兩個方法來洗掉檔案系統中的物件,使用哪一個方法取決于具體的型別,要洗掉一個空目錄,可以使用rmdir(),
import pathlib p = pathlib.Path('example_dir') print('Removing {}'.format(p)) p.rmdir()

如果后置推薦已經滿足而目錄不存在,則會產生一個FileNotFoundError例外,如果試圖洗掉一個不為空的目錄,則也會出現錯誤,

對于檔案、符號鏈接和大多數其他路徑型別,可以使用unlink(),
import pathlib p = pathlib.Path('touched') p.touch() print('exists before removing:', p.exists()) p.unlink() print('exists after removing:', p.exists())
用戶必須有洗掉檔案、符號鏈接、套接字或其他檔案系統物件的權限,

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/178310.html
標籤:Python
上一篇:python筆記28(TCP,UDP,socket協議)
下一篇:python globals函式
