這篇“Python上下文管理器是什么及怎么使用”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“Python上下文管理器是什么及怎么使用”文章吧。
創(chuàng)新互聯(lián)建站專注于田陽企業(yè)網(wǎng)站建設,響應式網(wǎng)站,商城系統(tǒng)網(wǎng)站開發(fā)。田陽網(wǎng)站建設公司,為田陽等地區(qū)提供建站服務。全流程定制開發(fā),專業(yè)設計,全程項目跟蹤,創(chuàng)新互聯(lián)建站專業(yè)和態(tài)度為您提供的服務
上下文管理器是一個對象,它定義了在執(zhí)行with語句時要建立的運行時上下文。上下文管理器是為代碼塊所執(zhí)行的上下文環(huán)境自動處理進入和退出所需的運行時。上下文管理器通常使用with語句調用,但也可以通過直接調用它們的方法來使用。
上下文管理器的典型用途包括保存和恢復各種全局狀態(tài),鎖定和解鎖資源,關閉打開的文件,等等。
with語句用于上下文管理器定義的方法包裝塊的執(zhí)行。這允許封裝常見的try…except…finally使用模式以方便重用。與傳統(tǒng)的try…except…finally塊相比,with語句提供了更短且可重用的代碼。
在Python標準庫中,許多類都支持with語句。一個非常常見的例子是內置的open()函數(shù),它提供了使用with語句處理文件對象的模式。
下面是with語句的一般語法:
with expression as target: # 使用target # 來處理事情
我們看一個使用open()函數(shù)的例子。在當前項目的files文件夾中有一個文本文件。文件名為color_names.txt,其中包含一些顏色名稱(可自行提供一些文本內容)。我們希望通過使用open()函數(shù)和with語句打開并打印該文件中的內容。代碼示例如下:
import os fileDirPath = os.getcwd()+os.sep+"ctxManager"+os.sep #自定義文件路徑 # 指定文件路徑和名稱 path = fileDirPath+'files/color_names.txt' # with 語句 with open(path, mode='r') as file: # 讀取文件內容 print(file.read())
運行程序輸出結果如下
red orange yellow green blue white black
在上面清單中,所看到是with語句的一個常見用例。我們使用open()函數(shù)打開給定的路徑(path)上的文件,且open()函數(shù)以只讀模式返回文件對象。然后代碼中使用這個文件對象讀取并通過代碼:print(file.read())將其內容打印輸出。
上面示例是上下文管理器的一個典型用法。為了更好地理解和應用上下文管理器,我們還得繼續(xù)往下看。
上下文管理器協(xié)議(Context Manager Protocol),說白了就是上下文管理器的處理機制,或說預定的規(guī)約標準。這部分內容也可查看這里:Python核心協(xié)議。為了閱讀的獨立性,這里也再說一說。
Python的with語句支持由上下文管理器定義的運行時上下文的概念。這是通過一對方法實現(xiàn)的,它們允許用戶定義的類定義運行時上下文,該上下文在語句體執(zhí)行之前進入,并在語句結束時退出。
前所提到的這些方法稱為上下文管理器協(xié)議。來具體看一下這兩個方法:
1)__enter__(self)
該方法由with語句調用,以進入與當前對象相關的運行時上下文。with語句將此方法的返回值綁定到語句的as子句中指定的目標(如果有的話)。
上例中返回的上下文管理器的是文件對象。在背后,文件對象從__enter__()返回其本身,以允許open()被用作with語句中的上下文表達式。
2)__exit__(self, exc_type, exc_value, traceback):
當執(zhí)行離開with代碼塊時調用此方法。它退出與此對象相關的運行時上下文。參數(shù)描述了導致退出上下文的異常信息。如果沒有異常而退出上下文,那么所有三個參數(shù)都將為None。
如果提供了異常,并且希望該方法抑制該異常(即,阻止它被傳播),那么它應該返回一個True值。否則,異常將在退出此方法時正常處理。__exit__()方法返回一個布爾值,可以是True或False。
使用上下文管理器協(xié)議中的方法執(zhí)行with語句的過程如下:
with EXPRESSION as TARGET: SUITE
計算上下文表達式(EXPRESSION)以獲得上下文管理器。
加載上下文管理器的__enter__()以供隨后使用。
加載上下文管理器的__exit__()以供隨后使用。
調用上下文管理器的__enter__()方法。
如果在with語句中包含了一個TARGET,則會將__enter__()的返回值賦給它。
執(zhí)行套件(with語句作用域中的代碼塊)。
調用上下文管理器的__exit__()方法。如果異常導致套件退出,則其類型、值和回溯將作為參數(shù)傳遞給__exit__()。否則,將提供三個None參數(shù)。
如果套件因異常以外的任何原因退出,則會忽略__exit__()的返回值,并在所執(zhí)行退出類型的正常位置繼續(xù)執(zhí)行后續(xù)代碼(若有)。
現(xiàn)在我們了解了上下文管理器協(xié)議背后的基本思想,讓我們在一個類中實現(xiàn)它。這個類將是我們的上下文管理器,并稍后在with語句中使用它。
定義的上下文管理器類參考示例清單如下:
# 自定義上下文管理器類 class CustomContextManager: # 初始化方法init -> 定義一些變量 def __init__(self, path, mode): self.path = path self.mode = mode self.file = None # __enter__ method -> open the file def __enter__(self): self.file = open(self.path, self.mode) return self.file # exit method to close the file def __exit__(self, exc_type, exc_value,exc_traceback): self.file.close()
我們的CustomContextManager類實現(xiàn)了成為上下文管理器的必要方法:__enter__和__exit__。
在__init__方法中,它定義了三個實例變量來存儲路徑、模式和文件對象。
在__enter__方法中,它使用內置的open()函數(shù)打開指定路徑中的文件。由于open()函數(shù)返回file對象,我們將其賦值給self.file屬性。
在__exit__方法中,我們將文件關閉:self.file.close()。
__exit__方法接受三個參數(shù),它們是上下文管理器協(xié)議所需要的。
現(xiàn)在我們可以在with語句中使用自定義上下文管理器。
使用自定義的類上下文管理器的示例(和我們前面的示例雷同):
# 應用示例 import os fileDirPath = os.getcwd()+os.sep+"ctxManager"+os.sep # 在with語句中使用自定義上下文管理器 file_path = fileDirPath + 'files/color_names.txt' with CustomContextManager(path=file_path, mode='r') as file: #輸出文件file內容 print(file.read())
運行輸出結果這里不再贅述。簡單解釋一下代碼。
上面清單中,在with語句中使用CustomContexManager類,通過它來讀取文件內容并打印出來。下面是這個自定義上下文管理器幕后的故事:
1)在with行,調用類CustomContextManager的方_enter__法
2) __enter__方法打開文件并返回它。
3)我們將打開的文件簡單地命名為file。
4)在with語句塊中,讀取文件內容并將其打印出來。
5)with語句自動調用__exit__方法。
6)__exit__方法關閉文件。
我們再來定義另一個上下文管理器類。這次我們想打印指定文件夾中的文件列表。
參考實現(xiàn)的代碼清單如下:
class ContentList:
'''Prints the content of a directory'''
def __init__(self, directory):
self.directory = directory
def __enter__(self):
return os.listdir(self.directory)
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type is not None:
print("Error getting directory list.")
return True
# 輸出項目目錄下的內容
project_directory = '.'
with ContentList(project_directory) as directory_list:
print(directory_list)在代碼清單中,我們定義了一個新的上下文管理器。這個類的名字是ContentList。為什么它是一個上下文管理器?因為它實現(xiàn)了上下文管理器協(xié)議(__enter__和__exit__方法)。
我們將目錄路徑作為類構造函數(shù)__init__方法中的參數(shù)。
在__enter__方法中,只需調用os模塊中的listdir()方法,就可以獲得該目錄中的內容列表:os.listdir(self.directory)。然后返回這個列表。請注意,在這個上下文管理器中我們的__enter__方法返回一個列表。
在__exit__方法中,我們檢查是否存在任何錯誤。如果我們的上下文管理器中有錯誤,exc_type、exc_val、exc_tb參數(shù)值將不會為None。因此,我們檢查exc_type是否為None以打印錯誤文本。
在with語句中使用該上下文管理器。由于它返回一個列表對象,我們只需將返回值賦值給directory_list變量。在with語句的主體中,我們打印這個列表。運行程序后在輸出中,可以看到項目目錄中的內容列表。記住,"."表示當前目錄,在我們的例子中是項目根目錄(由于項目環(huán)境不同,輸出內容可能也不一樣)。
前文中,我們學習了如何使用類語法定義上下文管理器。但是有點繁瑣和冗長。因為需要明確地實現(xiàn)__enter__和exit__方法,還需要處理可能的異常。所以希望Python中能有在創(chuàng)建上下文管理器更好的方法:基于函數(shù)的上下文管理器。
其實函數(shù)上下文管理器是使用生成器和contextlib.contextmanager裝飾器的特殊函數(shù)。 contextlib.contextmanager裝飾器負責實現(xiàn)上下文管理器協(xié)議。
下面就來定義一個函數(shù)型上下文管理器。
from contextlib import contextmanager
# 定義上下文管理器函數(shù)
@contextmanager
def function_based_context_manager():
print("進入上下文: __enter__")
yield "這是個基于上下文管理器的函數(shù)"
print("離開上下文: __exit__")
# with語句中使用上下文管理器函數(shù)
with function_based_context_manager() as yield_text:
print(yield_text)運行程序輸出結果類似如下:
進入上下文: __enter__ 這是個基于上下文管理器的函數(shù) 離開上下文: __exit__
在上面代碼中,我們定義了一個作為上下文管理器的自定義函數(shù)。contextmanager裝飾器將常規(guī)函數(shù)轉換為全堆棧上下文管理器(自動實現(xiàn)上下文管理器的協(xié)議)。如果你為函數(shù)提供了@contextmanager裝飾器,就不需要擔心實現(xiàn)__enter__和__exit__函數(shù)。
代碼中的yield語句在基于類的上下文管理器中的__enter__方法中充當返回語句。由于我們使用了yield語句,故此,這個基于函數(shù)的上下文管理器也是生成器函數(shù)。
再來定義一個新的上下文管理器。這一次,它將以寫的模式打開一個文件并添加一些文本。示例如下:

在清單中,我們定義了一個基于函數(shù)的上下文管理器。在try塊中,它嘗試打開指定路徑中的文件,并指定了文件的默認編碼集。如果它成功地打開它,那么它將生成(返回)file_object。在finally塊中,我們檢查是否有一個file_object要關閉。如果file_object不是None,則關閉file_object。
在with語句中,我們用文件名funBasedContextManagers.txt調用上下文管理器。上下文管理器以寫模式打開該文件并返回文件對象,我們將其簡單命名為file。接著在這個文件中寫入一些文本。記住,如果這樣的文件不存在,'w'模式將創(chuàng)建一個空文件。
運行上面程序,若文件不存在,則生成相應名稱的文件并保持寫入的內容。若文件存在,則這種寫入文件是每次情況源文件再寫入內容的,這一點操作請注意。
像這種處理“收尾”工作的,使用上下文管理器特別方便,尤其涉及到數(shù)據(jù)庫操作方面,比如可以自己包裝一個來完成自動的關閉連接等。
以上就是關于“Python上下文管理器是什么及怎么使用”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
網(wǎng)站名稱:Python上下文管理器是什么及怎么使用
標題鏈接:http://www.chinadenli.net/article6/gpcjig.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供微信小程序、品牌網(wǎng)站設計、網(wǎng)站設計公司、網(wǎng)站建設、App設計、商城網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)