linecache模塊
接觸到linecache這個模塊是因為前兩天讀attrs源碼的時候看到內部代碼引用了這個模塊來模擬一個假文件,帶著一臉疑問順便讀了一下這個模塊的源碼,發現其實也就那么回事兒,代碼不多,在這總結一下。
linecache模塊可以讀取文件并將文件內容緩存起來,方便后面多次讀取。這個模塊原本被設計用來讀取Python模塊的源代碼,所以當一個文件名不在指定路徑下的時候,模塊會通過搜索路徑(search path)來嘗試讀取文件。
接口
linecache模塊的__all__參數其實只提供了getline/clearcache/checkcache三個接口,但實際上可以使用的不止這些,下面我會對所有接口逐個進行介紹。
linecache.getline(filename, lineno, module_globals=None)
獲取指定文件的某一行,filename指定文件名、lineno指定行號、module_globals用于指定模塊的上下文我也不知道怎么稱呼,姑且稱為上下文吧,最后一個參數其實到會傳到linecache.updatecache()里,用于嘗試使用__loader__加載文件,一般情況下不會用到最后一個參數,忽略即可。當行號小于一或大于文件最大行號時函數直接返回空字符串。
linecache.clearcache()
清空所有緩存,注意是所有。
linecache.checkcache(filename=None)
這個函數用于檢查緩存,如果文件的大小或者修改時間有變化,會把文件原先的緩存刪除,如果文件是懶加載的則保持不變。當filename為None時檢查緩存中的所有文件。
以下是沒寫進模塊__all__參數的接口。
linecache.lazycache(filename, module_globals)
對指定文件使用懶加載,啟用懶加載成功的文件會在實際調用獲取內容的接口時才將文件內容加載進內存,使用這個可以避免多余的文件IO。返回值為一個布爾值,當懶加載成功時返回True,如果文件內容已經實際加載進內存或者加載失敗則返回False。
這個函數的module_globals參數是必填的,其實就是傳入要加載文件對應模塊的上下文。比如加載linecache模塊,則傳入linecache.__dict__或者vars(linecache)(目前只想到這兩種方法,當然你要自己構建一個字典傳進去也是可以的)。然后函數會根據上下文獲取__loader__的get_source函數保存到緩存中。這個函數是在Python3.5后新增的。
linecache.updatecache(filename, module_globals=None)
這個函數是整個模塊的核心,用于更新文件緩存并返回文件內容。函數中間任何一個環節出錯了會返回一個空列表。
對于普通文件,內部使用tokenize.open()函數用于打開文件,檢測文件的編碼并使用檢測到的編碼打開文件,如果缺失編碼默認使用UTF-8。如果給定路徑無法打開文件則使用sys.path指定的路徑嘗試加載。如果文件內容的最后一行不帶/n,會自動在最后一個字符加上/n。
新聞熱點
疑難解答