今天看書,書上面提到要盡量使用with自動關閉資源,裡面還提到了上下文管理器物件的概念,然後查詢資料,對with的解釋如下:with的有一些任務,可能事先需要設定,事後做清理工作。對於這種場景,python的with語句提供了一種非常方便的處理方式。乙個很好的例子是檔案處理,需要獲取乙個檔案控制代碼,從檔案中讀取資料,然後關閉檔案控制代碼。下面就講下with語句以及上下文管理器物件,希望對你有幫助。
(一)with語句
對於檔案操作完成後,應該要關閉它,這是乙個常識,因為開啟的檔案不僅占用了系統資源,而且可能影響其它程式或程序的操作,甚至會導致使用者期望與實際操作結果不一樣。with語句得語法為
with 表示式 [as 目標]:
**塊with語句支援巢狀,支援多個with子句,它們兩者可以相互轉換。"with expr1 as e1,expr2 as e2"與下面的巢狀形式等價
1
2
with expr1 as e1:
with expr2 as e2:
with語句使用比較簡單。如下面例子不使用with的時候**如下
1
2
3
f
=
open
(
'test.txt'
,
'w'
)
f.write(
"hello"
)
f.close()
#這句很容易被忘記,這也是為什麼推薦使用with
使用with語句**如下:
1
2
with
open
(
'test.txt'
,
'w'
) as f:
f.write(
"hello"
)
with語句可以在**塊執行完畢後,還原到進入該**塊時的現場(這句話要仔細理解,也就是說with裡的**塊執行完後,會返回到剛剛進入with時的現場)。with語句**塊執行過程如下:
(1)計算表示式的值,返回乙個上下文管理器物件
(2)載入上下文管理器物件的__exit__()方法以備後用
(3)呼叫上下文管理器物件的__enter__()方法
(4)如果with語句中設定了目標物件,則將__enter__()方法的返回值賦值給目標物件(比如上面的f)
(5)執行with裡的**塊
(6)如果步驟(5)**正常結束,呼叫上下文管理器物件的__exit__()方法,返回值直接忽略
(7)如果步驟(5)中**異常,呼叫上下文管理器物件的__exit__(),並將異常型別、值以及traceback資訊作為引數傳遞給__exit__()方法。如果__exit__()返回值為false,則異常會被重新丟擲;如果返回的是true,異常被掛起,程式繼續執行
使用with的好處是無論程式以何種方式跳出with塊,總能保證資源被正確關閉。下面介紹一下上下文管理器物件。
(二)上下文管理器物件
with的神奇之處得益於乙個成為上下文管理器的(context manager)的東西,它用來建立乙個這樣的物件:它定義程式執行時需要建立的上下文,處理程式的進入和退出,實現上下文管理協議,即在物件中定義__enter__()和__exit__()方法(這兩個方法可以過載,這就說明,我們可以自定義屬於自己的上下文管理器,待會兒再介紹),其中:
__enter__(self):進入執行時的上下文,也就是進入上下文管理器時呼叫該函式,返回執行時的上下文物件,with語句中會將這個返回值繫結到目標物件上(上面的例子就是繫結到f上)。順便說下上下文表示式(context expression),上下文表示式指with 語句中跟在關鍵字 with 之後的表示式,該表示式要返回乙個上下文管理器物件,該物件就被賦值給了目標物件。
__exit__(self,exception_type,exception_value,traceback):退出執行時的上下文,定義在塊執行(或終止)之後上下文管理器應該做什麼。它可以處理異常、清理現場或者處理with塊中語句執行完成後需要處理的動作。exception_type,exception_value,traceback三個引數代表的意思分別是異常的型別、值和追蹤資訊。如果沒有異常,3個引數均設為none。此方法返回值為true或者false,分別指示被引發的異常得到了還是沒有得到處理。如果返回false,引發的異常會被傳遞出上下文。這個在前面簡單的提到過,希望你能結合上下文仔細理解這些東西。
實際上任何實現了上下文協議的物件都可以稱為乙個上下文管理器,檔案也是實現了這個協議的上下文管理器,它們都能夠與with語句相容。檔案物件的__enter__()和__exit__()屬性如下 1
2
3
4
>>>f.__enter__
>>>f.__exit__
當然我們也可以定義自己的上下文管理器,只要實現了上下文協議便可以和with語句一起使用。如下面例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class
openfile(
object
):
def
__init__(
self
,filename,mode):
self
.filename
=
filename
self
.mode
=
mode
def
__enter__(
self
):
self
.f
=
open
(
self
.filename,
self
.mode)
return
self
.f
#作為as說明符指定的變數的值
def
__exit__(
self
,exception_type,exception_value,traceback):
if
exception_type
is
none
:
#如果沒有異常,正常關閉資源
self
.f.close()
else
:
#有異常發生
print
exception_value
print
traceback
return
false
#返回false則異常會被重新丟擲
with openfile(
'my_file.txt'
,
'w'
) as f:
f.write(
'hello'
)
f.write(
'world'
)
上下文管理器主要作用於資源共享,因此在實際應用中__enter__()和__exit__()方法基本用於資源分配以及釋放相關的工作,如開啟/關閉檔案、異常處理、斷開流的連線、鎖分配等。為了更好的輔助上下文管理器,python還提供了contextlib模組,這個下次有機會再講。技術有限,不正之處,請多多包涵!
python with 語句研究
import sys class test def enter self print enter return 1 def exit self,args print exit return true with test as t print t is not the result of test i...
python with上下文管理
class person def init self,name self name name def enter self print 這是with定義的物件進到了enter方法中執行操作 return self def exit self,exc type,exc value,exc tb pri...
Python with語句和過程抽取思想
python中的with語句使用於對資源進行訪問的場合,保證不管處理過程中是否發生錯誤或者異常都會執行規定的 exit 清理 操作,釋放被訪問的資源,比如有檔案讀寫後自動關閉 執行緒中鎖的自動獲取和釋放等。與python中with語句有關的概念有 上下文管理協議 上下文管理器 執行時上下文 上下文表...