本文和大家分享的是python
中上下文管理器相關(guān)內(nèi)容,上下文管理器主要用于規(guī)定某個對象的使用范圍,下面將詳細(xì)圍繞上下文管理器使用方法、實(shí)現(xiàn)機(jī)制等方面展開介紹,一起來看看吧,希望對大家
學(xué)習(xí)python有所幫助。
為什么需要上下文管理器?
首先,需要思索下為什么需要引入上下文管理器。
在正常情況下,管理各種系統(tǒng)資源(如文件)、數(shù)據(jù)庫連接時,通常是先打開這些資源,執(zhí)行完相應(yīng)的業(yè)務(wù)邏輯,最后關(guān)閉資源。
舉兩個例子:
1.
使用
Python
打開一個文件寫入內(nèi)容,之后需要關(guān)閉這個文件。如果不正常關(guān)閉的話可能會在文件操作時出現(xiàn)異常,因?yàn)橄到y(tǒng)允許你打開的文件的最大數(shù)是有限的。
2.
在數(shù)據(jù)庫連接時也是存在類似問題,數(shù)據(jù)庫的連接算是一種比較昂貴的資源,若連接過多而沒有及時關(guān)閉的話,就可能出現(xiàn)不能繼續(xù)連接的異常錯誤。
但是,很多程序員經(jīng)常會忘記關(guān)閉文件,或者關(guān)閉數(shù)據(jù)庫的連接。這時候就引入了
上下文管理器
,它可以在你不需要該對象的時候,自動關(guān)閉它。
上下文管理器怎么使用?
上下文管理器的語法是:with...as...
實(shí)例:文件操作
print "
不使用上下文管理器
"
print "*" * 30
f =
open('file.py', 'w')
print
f.closed
f.
write("# Hello World")
f.
close()
print
f.closed
print "\n
使用上下文管理器
"
print "*" * 30
with
open("file.py", 'w')
as
f:
print
f.closed
f.
write('# Hello Python')
print
f.closed
這里通過.closed
比較,我們可以看到上下文管理器可以自動關(guān)閉文件,對于上下文管理器而言,有隸屬于它的程序塊,當(dāng)隸屬于它的程序塊執(zhí)行結(jié)束的時候(判斷縮進(jìn)),上下文管理器將自動關(guān)閉文件。
上述實(shí)例,也可以使用try...except...
來實(shí)現(xiàn),同樣可以很直觀的看到使用
with...as...
語句之后,代碼確實(shí)相對更加簡潔。
上下文管理實(shí)現(xiàn)機(jī)制
因?yàn)槲募ο笫?/span>Python
的內(nèi)置對象,內(nèi)置了上下文管理的特殊方法,所以它可以使用
with
語句。在
Python
中,任何對象,只要實(shí)現(xiàn)了上下文管理,就可以使用
with
語句,實(shí)現(xiàn)上下文管理需要通過
__enter__
和
__exit__
這兩個方法來實(shí)現(xiàn)。
關(guān)于這兩個方法:
·
enter (self)
:進(jìn)入該對象時調(diào)用此方法,返回值將放入
with...as...
語句中的
as
說明的變量中
·
exit (self, type, value, tb):
離開上下文管理器時調(diào)用該方法,如果有異常出現(xiàn),返回
False
,
type
、
value
和
tb
將分別表示異常的類型、值和追蹤信息,傳遞出上下文顯示;如果沒有異常,則三個變量的值均為
None
。
with
上下文管理器:
語法體
當(dāng)with
語句遇到上下文管理器時,就會在執(zhí)行語法體之前,先執(zhí)行
__enter__
方法,然后再執(zhí)行語法體,執(zhí)行完語法體之后,執(zhí)行
__exit__
方法。
上下文管理器實(shí)現(xiàn)
使用Python2.7X
實(shí)現(xiàn)一個上下文管理器
:
class
Context(object):
def
__init__(self):
print "
實(shí)例化一個對象
"
def
__enter__(self):
print "
獲取該對象
"
def
__exit__(self, exc_type, exc_val, exc_tb):
print "
退出該對象
"
temp = Context()
with temp:
print "
執(zhí)行體
"
這樣,__enter__
方法和
__exit__
方法的調(diào)用過程就很明晰。
contextLib
在contextlib
中,提供了
contextmanager
裝飾器,通過
yield
返回函數(shù)將函數(shù)分隔為兩部分,
yield
之前的語句在
__enter__
中執(zhí)行,
yield
之后的語句在
__exit__
中執(zhí)行,簡化了上下文管理器的實(shí)現(xiàn)方式:
總結(jié):通過上下文管理器,我們可以更好的控制對象在不同區(qū)間的特性,并且可以使用with
語句替代
try...except
方法,使得代碼更加的簡潔,主要的使用場景是訪問資源,可以保證不管過程中是否發(fā)生錯誤或者異常都會執(zhí)行相應(yīng)的清理操作,釋放出訪問的資源。
來源:網(wǎng)絡(luò)