用 Python 做一件很平常的事情: 打開文件, 逐行讀入, 最后關掉文件; 進一步的需求是, 這也許是程序中一個可選的功能, 如果有任何問題, 比如文件無法打開, 或是讀取出錯, 那么在函數內需要捕獲所有異常, 輸出一行警告并退出. 代碼可能一開始看起來是這樣的
def read_file(): try: f = open('yui', 'r') print ''.join(f.readlines()) except: print 'error occurs while reading file' finally: f.close()
不過這顯然無法運作, 因為 f 是在 try 塊中定義的, 而在 finally 中無法引用.
如果將 f 提取到 try 塊外部, 如
def read_file(): f = open('azusa', 'r') try: print ''.join(f.readlines()) except: print 'error occurs while reading file' finally: f.close()
那么, 問題在于當打開文件失敗, 拋出異常將不會被捕獲.
挫一點的方法自然是, 再套一層 try 吧
def read_file(): try: f = open('sawako', 'r') try: print ''.join(f.readlines()) except: print 'error occurs while reading file' finally: f.close() except: print 'error occurs while reading file'
當然這不僅僅是多一層縮進挫了, 連警告輸出都白白多一次呢.
正規一點的方式是, 使用 Python 引入的 with 結構來解決, 如
def readFile(): try: with open('mio', 'r') as f: print ''.join(f.readlines()) except: print 'error occurs while reading file'
當文件打開失敗時, 異常自然會被 except 到; 否則, 在 with 塊結束之后, 打開的文件將自動關閉.
除了打開文件, 還有其它這樣可以用于 with 的東西么? 或者說, 怎么自定義一個什么東西, 讓它能用于 with 呢?
直接回答后一個問題吧, 秘密在于 Python 虛擬機在 with 塊退出時會去尋找對象的 __exit__ 方法并調用它, 把釋放資源的動作放在這個 __exit__ 函數中就可以了; 另外, 對象還需要一個 __enter__ 函數, 當進入 with 塊時, 這個函數被調用, 而它的返回值將作為 as 后引用的值. 一個簡單的例子是
class Test: def __init__(self): print 'init' def __enter__(self): print 'enter' return self def __exit__(self, except_type, except_obj, tb): print except_type print except_obj import traceback print ''.join(traceback.format_tb(tb)) print 'exit' return True with Test() as t: raise ValueError('kon!')
新聞熱點
疑難解答