1. linecache高效讀取文本文件
處理Python源文件時,在Python標准庫的其他部分中用到了linecache模塊。緩存實現將在內存中保存文件的內容(解析為單獨的行)。這個API通過索引一個list來返回請求的行,與反復的讀取文件並解析文本來查找所需文本行相比,這樣可以節省時間。這個模塊在查找同一個文件中的多行時尤其有用,比如為一個錯誤報告生成一個跟蹤記錄(traceback)。
1.1 測試數據
公共數據如下:
import os import tempfile import linecache lorem = '''Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Vivamus eget elit. In posuere mi non risus. Mauris id quam posuere lectus sollicitudin varius. Praesent at mi. Nunc eu velit. Sed augue massa, fermentum id, nonummy a, nonummy sit amet, ligula. Curabitur eros pede, egestas at, ultricies ac, apellentesque eu, tellus. Sed sed odio sed mi luctus mollis. Integer et nulla ac augue convallis accumsan. Ut felis. Donec lectus sapien, elementum nec, condimentum ac, interdum non, tellus. Aenean viverra, mauris vehicula semper porttitor, ipsum odio consectetuer lorem, ac imperdiet eros odio a sapien. Nulla mauris tellus, aliquam non, egestas a, nonummy et, erat. Vivamus sagittis porttitor eros.''' def make_tempfile(): fd, temp_file_name = tempfile.mkstemp() os.close(fd) with open(temp_file_name, 'wt') as f: f.write(lorem) return temp_file_name def cleanup(filename): os.unlink(filename)
filename = make_tempfile()
1.2 讀取特定行
linecache模塊讀取的文件行好從1開始,不過通常列表的數組索引會從0開始。
# Pick out the same line from source and cache. # (Notice that linecache counts from 1) print('SOURCE:') print('{!r}'.format(lorem.split('\n')[4])) print() print('CACHE:') print('{!r}'.format(linecache.getline(filename, 5))) cleanup(filename)
返回的各行包括末尾的一個換行符。
1.3 處理空行
返回值總是在行末尾包含一個換行符,所以如果文本行為空,則返回值就是一個換行符。
# Blank lines include the newline print('BLANK : {!r}'.format(linecache.getline(filename, 8))) cleanup(filename)
輸入文件的第8行不包含任何文本。
1.4 錯誤處理
如果所請求的行號超出了文件中合法行號的范圍,則getline()會返回一個空串。
# The cache always returns a string, and uses # an empty string to indicate a line which does # not exist. not_there = linecache.getline(filename, 500) print('NOT THERE: {!r} includes {} characters'.format( not_there, len(not_there)))
輸入文件只有15行,所以請求第500行就類似於試圖越過文件末尾繼續讀文件。
讀取一個不存在的文件時,也采用同樣的方式處理。
# Errors are even hidden if linecache cannot find the file no_such_file = linecache.getline( 'this_file_does_not_exist.txt', 1, ) print('NO FILE: {!r}'.format(no_such_file))
調用者試圖讀取數據時,這個模塊不會產生異常。
1.5 讀取Python源文件
由於生成traceback跟蹤記錄時linecache使用得非常頻繁,其關鍵特性之一是能夠指定模塊的基名在導入路徑中查找Python源模塊。
# Look for the linecache module, using # the built in sys.path search. module_line = linecache.getline('linecache.py', 3) print('MODULE:') print(repr(module_line)) # Look at the linecache module source directly. file_src = linecache.__file__ if file_src.endswith('.pyc'): file_src = file_src[:-1] print('\nFILE:') with open(file_src, 'r') as f: file_line = f.readlines()[2] print(repr(file_line))
如果linecache中的緩存填充代碼在當前目錄中無法找到指定名的文件,那么它會在sys.path中搜索指定名的模塊。這個例子要查找linecache.py。由於當前目錄中沒有這個文件副本,所以會找到標准庫中相應的文件。