精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Python新增功能 詳解上下文管理器

開發 后端 前端
上下文管理器是在Python2.5加入的功能,它能夠讓你的代碼可讀性更強并且錯誤更少。接下來,讓我們來看看該如何使用。

這篇文章是關于什么的?

  • 什么是Python中的上下文管理器
  • 怎么使用上下文管理器
  • 如何創建自己的上下文管理器
  • 關于Python上下文庫(contextlib)

1. 上下文管理器是什么?

舉個例子,你在寫Python代碼的時候經常將一系列操作放在一個語句塊中:

當某條件為真 – 執行這個語句塊

當某條件為真 – 循環執行這個語句塊

有時候我們需要在當程序在語句塊中運行時保持某種狀態,并且在離開語句塊后結束這種狀態。

所以,事實上上下文管理器的任務是 – 代碼塊執行前準備,代碼塊執行后收拾。

上下文管理器是在Python2.5加入的功能,它能夠讓你的代碼可讀性更強并且錯誤更少。接下來,讓我們來看看該如何使用。

context1

2. 如何使用上下文管理器?

看代碼是***的學習方式,來看看我們通常是如何打開一個文件并寫入”Hello World”?

  1. filename = 'my_file.txt' 
  2. mode = 'w' # Mode that allows to write to the file  
  3. writer = open(filename, mode)  
  4. writer.write('Hello ')  
  5. writer.write('World')  
  6. writer.close() 

1-2行,我們指明文件名以及打開方式(寫入)。

第3行,打開文件,4-5行寫入“Hello world”,第6行關閉文件。

這樣不就行了,為什么還需要上下文管理器?但是我們忽略了一個很小但是很重要的細節:如果我們沒有機會到達第6行關閉文件,那會怎樣?

舉個例子,磁盤已滿,因此我們在第4行嘗試寫入文件時就會拋出異常,而第6行則根本沒有機會執行。

當然,我們可以使用try-finally語句塊來進行包裝:

  1. writer = open(filename, mode)  
  2. try:  
  3.     writer.write('Hello ')  
  4.     writer.write('World')  
  5. finally:  
  6.     writer.close() 

finally語句塊中的代碼無論try語句塊中發生了什么都會執行。因此可以保證文件一定會關閉。這么做有什么問題么?當然沒有,但當我們進行一些比寫入“Hello world”更復雜的事情時,try-finally語句就會變得丑陋無比。例如我們要打開兩個文件,一個讀一個寫,兩個文件之間進行拷貝操作,那么通過with語句能夠保證兩者能夠同時被關閉。

OK,讓我們把事情分解一下:

首先,創建一個名為“writer”的文件變量。

然后,對writer執行一些操作。

***,關閉writer。

這樣是不是優雅多了?

  1. with open(filename, mode) as writer:  
  2.     writer.write('Hello ')   
  3.     writer.write('World'

讓我們深入一點,“with”是一個新關鍵詞,并且總是伴隨著上下文管理器出現。“open(filename, mode)”曾經在之前的代碼中出現。“as”是另一個關鍵詞,它指代了從“open”函數返回的內容,并且把它賦值給了一個新的變量。“writer”是一個新的變量名。

2-3行,縮進開啟一個新的代碼塊。在這個代碼塊中,我們能夠對writer做任意操作。這樣我們就使用了“open”上下文管理器,它保證我們的代碼既優雅又安全。它出色的完成了try-finally的任務。

open函數既能夠當做一個簡單的函數使用,又能夠作為上下文管理器。這是因為open函數返回了一個文件類型(file type)變量,而這個文件類型實現了我們之前用到的write方法,但是想要作為上下文管理器還必須實現一些特殊的方法,我會在接下來的小節中介紹。

3. 自定義上下文管理器

讓我們來寫一個“open”上下文管理器。

要實現上下文管理器,必須實現兩個方法 – 一個負責進入語句塊的準備操作,另一個負責離開語句塊的善后操作。同時,我們需要兩個參數:文件名和打開方式。

Python類包含兩個特殊的方法,分別名為:__enter__以及__exit__(雙下劃線作為前綴及后綴)。

當一個對象被用作上下文管理器時:

__enter__ 方法將在進入代碼塊前被調用。

__exit__ 方法則在離開代碼塊之后被調用(即使在代碼塊中遇到了異常)。

下面是上下文管理器的一個例子,它分別進入和離開代碼塊時進行打印。

  1. class PypixContextManagerDemo:  
  2.    
  3.     def __enter__(self):  
  4.         print 'Entering the block' 
  5.    
  6.     def __exit__(self, *unused):  
  7.         print 'Exiting the block' 
  8.    
  9. with PypixContextManagerDemo():  
  10.     print 'In the block' 
  11.    
  12. #Output:  
  13. #Entering the block  
  14. #In the block  
  15. #Exiting the block 

注意一些東西:

  • 沒有傳遞任何參數。
  • 在此沒有使用“as”關鍵詞。
  • 稍后我們將討論__exit__方法的參數設置。

我們如何給一個類傳遞參數?其實在任何類中,都可以使用__init__方法,在此我們將重寫它以接收兩個必要參數(filename, mode)。

當我們進入語句塊時,將會使用open函數,正如***個例子中那樣。而當我們離開語句塊時,將關閉一切在__enter__函數中打開的東西。

以下是我們的代碼:

  1. class PypixOpen:  
  2.    
  3.     def __init__(self, filename, mode):  
  4.         self.filename = filename  
  5.         self.mode = mode  
  6.    
  7.     def __enter__(self):  
  8.         self.openedFile = open(self.filename, self.mode)  
  9.         return self.openedFile  
  10.    
  11.     def __exit__(self, *unused):  
  12.         self.openedFile.close()  
  13.    
  14. with PypixOpen(filename, mode) as writer:  
  15.     writer.write("Hello World from our new Context Manager!"

來看看有哪些變化:

3-5行,通過__init__接收了兩個參數。

7-9行,打開文件并返回。

12行,當離開語句塊時關閉文件。

14-15行,模仿open使用我們自己的上下文管理器。

#p#

除此之外,還有一些需要強調的事情:

如何處理異常

我們完全忽視了語句塊內部可能出現的問題。

如果語句塊內部發生了異常,__exit__方法將被調用,而異常將會被重新拋出(re-raised)。當處理文件寫入操作時,大部分時間你肯定不希望隱藏這些異常,所以這是可以的。而對于不希望重新拋出的異常,我們可以讓__exit__方法簡單的返回True來忽略語句塊中發生的所有異常(大部分情況下這都不是明智之舉)。

我們可以在異常發生時了解到更多詳細的信息,完備的__exit__函數簽名應該是這樣的:

  1. def __exit__(self, exc_type, exc_val, exc_tb) 

這樣__exit__函數就能夠拿到關于異常的所有信息(異常類型,異常值以及異常追蹤信息),這些信息將幫助異常處理操作。在這里我將不會詳細討論異常處理該如何寫,以下是一個示例,只負責拋出SyntaxErrors異常。

  1. class RaiseOnlyIfSyntaxError:  
  2.    
  3.     def __enter__(self):  
  4.         pass 
  5.    
  6.     def __exit__(self, exc_type, exc_val, exc_tb):  
  7.         return SyntaxError != exc_type 

4. 談一些關于上下文庫(contextlib)的內容

contextlib是一個Python模塊,作用是提供更易用的上下文管理器。

contextlib.closing

假設我們有一個創建數據庫函數,它將返回一個數據庫對象,并且在使用完之后關閉相關資源(數據庫連接會話等)

我們可以像以往那樣處理或是通過上下文管理器:

  1. with contextlib.closing(CreateDatabase()) as database:  
  2.     database.query() 

contextlib.closing方法將在語句塊結束后調用數據庫的關閉方法。

contextlib.nested

另一個很cool的特性能夠有效地幫助我們減少嵌套:

假設我們有兩個文件,一個讀一個寫,需要進行拷貝。

以下是不提倡的:

  1. with open('toReadFile''r') as reader:  
  2.     with open('toWriteFile''w') as writer:  
  3.         writer.writer(reader.read()) 

可以通過contextlib.nested進行簡化:

  1. with contextlib.nested(open('fileToRead.txt''r'),  
  2.                        open('fileToWrite.txt''w')) as (reader, writer):  
  3.     writer.write(reader.read()) 

在Python2.7中這種寫法被一種新語法取代:

  1. with open('fileToRead.txt''r') as reader, \  
  2.         open('fileToWrite.txt''w') as writer:  
  3.         writer.write(reader.read()) 

contextlib.contextmanager

對于Python高級玩家來說,任何能夠被yield關鍵詞分割成兩部分的函數,都能夠通過裝飾器裝飾的上下文管理器來實現。任何在yield之前的內容都可以看做在代碼塊執行前的操作,而任何yield之后的操作都可以放在exit函數中。

這里我舉一個線程鎖的例子:

鎖機制保證兩段代碼在同時執行時不會互相干擾。例如我們有兩塊并行執行的代碼同時寫一個文件,那我們將得到一個混合兩份輸入的錯誤文件。但如果我們能有一個鎖,任何想要寫文件的代碼都必須首先獲得這個鎖,那么事情就好辦了。如果你想了解更多關于并發編程的內容,請參閱相關文獻。

下面是線程安全寫函數的例子:

  1. import threading  
  2.    
  3. lock = threading.Lock()  
  4.    
  5. def safeWriteToFile(openedFile, content):  
  6.     lock.acquire()  
  7.     openedFile.write(content)  
  8.     lock.release() 

接下來,讓我們用上下文管理器來實現,回想之前關于yield和contextlib的分析:

  1. @contextlib.contextmanager  
  2. def loudLock():  
  3.     print 'Locking' 
  4.     lock.acquire()  
  5.     yield 
  6.     print 'Releasing' 
  7.     lock.release()  
  8.    
  9. with loudLock():  
  10.     print 'Lock is locked: %s' % lock.locked()  
  11.     print 'Doing something that needs locking' 
  12.    
  13. #Output:  
  14. #Locking  
  15. #Lock is locked: True  
  16. #Doing something that needs locking  
  17. #Releasing 

特別注意,這不是異常安全(exception safe)的寫法。如果你想保證異常安全,請對yield使用try語句。幸運的是threading。lock已經是一個上下文管理器了,所以我們只需要簡單地:

  1. @contextlib.contextmanager  
  2. def loudLock():  
  3.     print 'Locking' 
  4.     with lock:  
  5.         yield 
  6.     print 'Releasing' 

因為threading.lock在異常發生時會通過__exit__函數返回False,這將在yield被調用是被重新拋出。這種情況下鎖將被釋放,但對于“print ‘Releasing’”的調用則不會被執行,除非我們重寫try-finally。

如果你希望在上下文管理器中使用“as”關鍵字,那么就用yield返回你需要的值,它將通過as關鍵字賦值給新的變量。

原文鏈接: pypix.com   翻譯: 伯樂在線 熊崽Kevin

譯文鏈接: http://blog.jobbole.com/64175/

責任編輯:林師授 來源: 伯樂在線
相關推薦

2025-06-06 08:00:00

上下文管理器Python開發

2022-06-29 14:15:01

Python計時器上下文管理器

2022-11-03 08:29:32

編程管理器協議

2023-11-16 08:46:27

上下文管理器Python

2024-11-14 09:00:00

Python上下文管理器

2023-12-10 13:37:23

Python編程上下文管理

2017-05-11 14:00:02

Flask請求上下文應用上下文

2012-07-18 11:39:18

ibmdw

2012-12-31 10:01:34

SELinuxSELinux安全

2012-08-01 09:58:12

Mountain Li操作系統

2022-09-14 13:13:51

JavaScript上下文

2021-11-03 16:41:30

Windows 11操作系統微軟

2021-06-23 09:46:16

Python 3.10結構模式管理器

2015-07-08 10:25:05

Javascript上下文作用域

2022-09-15 08:01:14

繼承基礎設施基礎服務

2023-07-11 10:02:23

2022-10-28 16:24:33

Context上下文鴻蒙

2024-09-30 14:10:00

2025-03-18 08:14:05

2017-12-17 17:01:23

限界上下文系統模型
點贊
收藏

51CTO技術棧公眾號

国产精品一区二区三区美女| 夜级特黄日本大片_在线| 一区视频在线| 日韩精品极品在线观看| 日本人视频jizz页码69| 亚洲综合图区| 久久青草国产手机看片福利盒子| 国产精品一区二区久久| 国产一级一级片| av一区二区高清| 日韩你懂的电影在线观看| 国产l精品国产亚洲区久久| 免费在线看黄色| 91免费看片在线观看| 成人网中文字幕| 亚洲 欧美 成人| 欧美va亚洲va日韩∨a综合色| 亚洲美女又黄又爽在线观看| 日本中文字幕在线不卡| 日韩福利一区| 亚洲一区二区三区四区在线| 一本一道久久a久久综合精品| 动漫av一区二区三区| 男人的天堂久久精品| 97涩涩爰在线观看亚洲| 国产午夜手机精彩视频| 激情婷婷综合| 亚洲国产精品va在线看黑人动漫| www.亚洲自拍| 日日夜夜精品| 欧美在线观看视频在线| 1024精品视频| 多野结衣av一区| 亚洲欧美二区三区| 亚洲精品一区二区三区av| 色吊丝在线永久观看最新版本| 国产一区二区在线观看视频| 国产精品一区二区女厕厕| 在线能看的av| 亚洲精品黄色| 久久乐国产精品| 久久久久久久久久一区二区三区| 欧美xxxxx视频| 伊人伊人伊人久久| 人妻大战黑人白浆狂泄| 婷婷精品在线| 日韩久久精品电影| 182在线视频| 欧美挤奶吃奶水xxxxx| 欧美成人三级电影在线| 九色91porny| 年轻的保姆91精品| 欧美一区二区三区精品| а 天堂 在线| 91视频成人| 911精品国产一区二区在线| 天堂网在线免费观看| 福利一区和二区| 欧美浪妇xxxx高跟鞋交| 在线观看日本www| 久久久久九九精品影院| 精品三级av在线| 久久久久亚洲av片无码v| 亚洲一区二区三区在线免费| 亚洲а∨天堂久久精品9966 | 亚洲风情在线资源| 色综合天天综合狠狠| 白嫩少妇丰满一区二区| 亚洲天堂1区| 在线播放欧美女士性生活| 亚洲男人天堂2021| 日本在线视频一区二区三区| 日韩欧美国产1| 国产真实乱人偷精品| 亚洲图片久久| 日韩中文字幕在线观看| 杨钰莹一级淫片aaaaaa播放| 欧美亚洲不卡| 欧美性受xxxx黑人猛交| 国产精品免费无遮挡无码永久视频| 日日骚欧美日韩| 91久久久国产精品| 亚洲精品国偷拍自产在线观看蜜桃 | 久久久噜噜噜久久| 欧美精品二区三区| 欧美a级一区二区| 亚洲一区二区三区视频播放| 日韩一级片免费观看| 久久久久久久久久久久久夜| 一区二区精品在线| 美女尤物在线视频| 色婷婷精品久久二区二区蜜臂av| av亚洲天堂网| 少妇一区二区三区| 日韩在线观看高清| 精品一区二区三区人妻| 天堂久久一区二区三区| 91在线观看欧美日韩| 污视频在线免费| 国产精品另类一区| 九一国产精品视频| 六九午夜精品视频| 亚洲精品久久久久久久久久久| 神马久久久久久久久久久| 欧美黄污视频| 国产精品三级久久久久久电影| 亚洲福利在线观看视频| 欧美激情在线看| www.av毛片| 四虎精品永久免费| 日韩电影免费在线观看中文字幕| 中文字幕第69页| 国产精品久久久久久模特| 国产在线视频一区| 国产美女性感在线观看懂色av | 欧美一级特黄aaaaaa在线看片| 蜜桃视频在线网站| 日韩精品资源二区在线| 亚洲av毛片基地| 午夜一级久久| 国产精品一区二区三区免费| 韩国av网站在线| 欧美视频在线一区| 成人免费无遮挡无码黄漫视频| 好看的av在线不卡观看| 亚洲一区二区三区视频| 欧美高清视频| 在线欧美日韩精品| 免费看黄色aaaaaa 片| 欧美三级不卡| 91久久国产自产拍夜夜嗨| av资源种子在线观看| 欧美午夜精品伦理| 国产高清成人久久| 欧美日韩网址| 91精品黄色| av免费在线免费| 666欧美在线视频| 精品女人久久久| 久久电影网电视剧免费观看| 日韩.欧美.亚洲| 国产综合色区在线观看| 亚洲天堂男人天堂| 成人公开免费视频| 国产视频在线观看一区二区三区| 亚洲精品中文字幕无码蜜桃| 国产99久久久国产精品成人免费| 4438全国成人免费| 人成免费电影一二三区在线观看| 欧美三级xxx| 国产亚洲无码精品| 久久蜜桃资源一区二区老牛| 日本在线播放不卡| 欧美日韩精品一区二区三区视频| 国产亚洲欧美另类中文| 久久国产乱子伦精品| 久久精品综合网| 国产v亚洲v天堂无码久久久| 成人毛片在线| 成人免费高清完整版在线观看| 成人免费网站在线观看视频| 日韩一区二区麻豆国产| 国产无码精品视频| 91日韩在线专区| 欧美韩国日本在线| 精品国产一区二区三区| 国产精品一二三在线| 操你啦视频在线| 亚洲丁香久久久| 在线视频一区二区三区四区| 久久精品视频在线免费观看| 在线看的黄色网址| 亚洲不卡av不卡一区二区| 成人免费在线一区二区三区| 日本不卡网站| 日韩在线视频中文字幕| 午夜精品久久久久久久91蜜桃| 亚洲成人福利片| 扒开jk护士狂揉免费| 免费成人在线观看视频| 成人国产一区二区三区| 麻豆成人入口| 国产精品三级久久久久久电影| 国产日产一区二区| 亚洲国产成人精品久久| 成人黄色三级视频| 亚洲男人的天堂在线aⅴ视频| 影音先锋黄色资源| 麻豆精品视频在线观看免费| 精品人妻人人做人人爽| 免费成人av| 99精品在线直播| 日韩精品99| 久久久久久久影院| 成人高清在线| 亚洲国产另类久久精品| 亚洲影院一区二区三区| 欧美日韩国产精品专区| 疯狂撞击丝袜人妻| 久久美女艺术照精彩视频福利播放| 日韩欧美亚洲另类| 久久国产66| 中文字幕の友人北条麻妃| 欧美天天综合| 激情欧美一区二区三区中文字幕| 色诱色偷偷久久综合| 4p变态网欧美系列| 日韩特级毛片| 日韩最新av在线| 秋霞av在线| 欧美精品一区二区在线播放| 一级特黄aaa大片在线观看| 亚洲大片在线观看| 无码人妻精品一区二区三区夜夜嗨| 91网上在线视频| 被黑人猛躁10次高潮视频| 免费观看在线综合| 久久精品99国产| 亚洲先锋成人| 在线观看18视频网站| 精品国产乱码久久久久久蜜坠欲下| 国产亚洲欧美一区二区三区| 粉嫩一区二区三区在线观看| 国产精品日韩在线| 另类专区亚洲| 97超级碰碰人国产在线观看| 99自拍视频在线观看| 日韩小视频在线| 番号在线播放| 国产亚洲精品高潮| 欧美色视频免费| 亚洲激情自拍图| 日韩一卡二卡在线| 欧美刺激午夜性久久久久久久| 一级特黄aa大片| 欧美猛男男办公室激情| 一级黄色片免费看| 欧美日韩一区三区| 国产一级精品毛片| 欧美亚洲一区二区在线| 波多野结衣不卡| 在线这里只有精品| 亚洲精品国产精品乱码视色| 日本高清不卡在线观看| 日韩免费av网站| 91福利国产成人精品照片| 亚洲s码欧洲m码国产av| 一本久久a久久免费精品不卡| 人妻丰满熟妇av无码区| 色综合av在线| 久久久久久av无码免费看大片| 色欧美88888久久久久久影院| 无码视频在线观看| 欧美午夜精品久久久久久超碰| 波多野结衣视频在线看| 欧美色国产精品| 97人妻精品一区二区三区软件| 欧美精选在线播放| 国产女人高潮的av毛片| 日韩精品一区二区在线观看| 亚洲欧美另类一区| 亚洲精品国产精品国自产在线| 亚洲人妻一区二区三区| 亚洲性xxxx| 顶级网黄在线播放| 欧美国产日韩视频| 樱花草涩涩www在线播放| 国产成人一区三区| 激情不卡一区二区三区视频在线| 97中文在线| 亚洲欧洲美洲国产香蕉| 亚洲激情一区二区三区| 欧美精品国产| 白嫩少妇丰满一区二区| 国内一区二区视频| 日本国产在线视频| 国产欧美一区二区三区鸳鸯浴| 极品色av影院| 午夜精品久久久久久不卡8050| 久久久久久久亚洲| 日韩免费看网站| 毛片免费在线| 久久视频在线看| 欧美sm一区| 成人av在线亚洲| 欧美巨大xxxx| 最新欧美日韩亚洲| 国产亚洲福利| 欧美成人福利在线观看| 成人av在线一区二区| 亚洲一级片在线播放| 亚洲综合男人的天堂| 日本精品入口免费视频| 欧美tickling挠脚心丨vk| 国产一区二区三区福利| 欧美精品videofree1080p| 韩国精品视频在线观看| 韩国成人av| 亚洲欧洲美洲一区二区三区| 日韩 欧美 高清| 国产盗摄视频一区二区三区| www.99热| 欧美日韩在线视频首页| 国产人妖一区二区| 中文字幕免费国产精品| 97蜜桃久久| 99高清视频有精品视频| 欧美视频网址| 免费在线激情视频| 丁香桃色午夜亚洲一区二区三区| 天堂资源在线视频| 欧美日韩国产中文字幕| а√中文在线资源库| 日韩视频在线免费| 日韩精品一区二区三区av| 含羞草久久爱69一区| 欧美日韩成人| 制服下的诱惑暮生| 国产精品人成在线观看免费| 国产一区免费看| 亚洲精品中文字幕av| 9765激情中文在线| 国产精品国产三级欧美二区| 91精品一区二区三区综合| 天天干天天草天天| 久久久久久久久蜜桃| 欧美在线观看不卡| 日韩成人在线观看| 阿v视频在线| 国产精品一码二码三码在线| 在线观看日韩| 免费人成视频在线播放| 亚洲欧美日韩在线| 国产精品污视频| 日韩在线小视频| www.久久爱.com| 婷婷精品国产一区二区三区日韩| 亚洲免费婷婷| 黄瓜视频污在线观看| 黑人精品xxx一区| 日韩一二三四| 日本亚洲精品在线观看| 亚洲区小说区图片区qvod按摩| 午夜肉伦伦影院| 2021国产精品久久精品| 欧产日产国产69| 一区二区国产精品视频| 51一区二区三区| 一区二区三区四区国产| 九九视频精品免费| a级黄色片免费看| 日韩欧美亚洲国产另类| 国产探花视频在线观看| 激情小说综合网| 日日摸夜夜添夜夜添精品视频| 精品熟妇无码av免费久久| 欧美精品亚洲一区二区在线播放| 国产在线观看免费麻豆| 福利视频久久| 日韩一级不卡| 国产成人一区二区在线观看| 欧美日韩一本到| 在线免费观看污| 精品久久久久久中文字幕动漫| 亚洲综合精品| 国产wwwwxxxx| 亚洲成年人影院在线| 成人欧美一区二区三区的电影| 亚洲人成影视在线观看| 国产成人精品亚洲午夜麻豆| 亚洲一区欧美在线| 中文字幕av一区中文字幕天堂| 国产精品毛片aⅴ一区二区三区| 免费网站在线观看视频| www亚洲一区| 91亚洲国产成人精品一区| 欧美理论电影在线播放| 九九综合九九| 肉色超薄丝袜脚交| 天天综合色天天综合色h| 色欧美激情视频在线| 国产精品一区二区欧美黑人喷潮水| 国产精品外国| 亚洲 欧美 变态 另类 综合| 精品国产精品网麻豆系列 | 亚洲free嫩bbb| 国产欧美日韩亚洲一区二区三区| 亚洲一二三四五六区| 亚洲精品在线一区二区| 日韩网站中文字幕| 国产情侣第一页| 亚洲国产精品国自产拍av| 亚洲国产日韩在线观看| 国产精品久久久久久中文字| 欧美视频导航| 亚洲色图欧美色| 亚洲高清免费观看高清完整版| 日韩深夜福利网站| 97视频在线免费播放| 一区二区三区蜜桃|