欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

簡(jiǎn)單介紹Python中的try和finally和with方法

 更新時(shí)間:2015年05月05日 11:41:04   作者:xrzs  
這篇文章主要介紹了Python中的try和finally和with方法,是Python學(xué)習(xí)當(dāng)中的基礎(chǔ)知識(shí),需要的朋友可以參考下

用 Python 做一件很平常的事情: 打開(kāi)文件, 逐行讀入, 最后關(guān)掉文件; 進(jìn)一步的需求是, 這也許是程序中一個(gè)可選的功能, 如果有任何問(wèn)題, 比如文件無(wú)法打開(kāi), 或是讀取出錯(cuò), 那么在函數(shù)內(nèi)需要捕獲所有異常, 輸出一行警告并退出. 代碼可能一開(kāi)始看起來(lái)是這樣的
 

def read_file(): 
  try: 
    f = open('yui', 'r') 
    print ''.join(f.readlines()) 
  except: 
    print 'error occurs while reading file'
  finally: 
    f.close()

    不過(guò)這顯然無(wú)法運(yùn)作, 因?yàn)?nbsp; f  是在  try  塊中定義的, 而在  finally  中無(wú)法引用.

    如果將  f  提取到  try  塊外部, 如
 

def read_file(): 
   f = open('azusa', 'r') 
  try: 
    print ''.join(f.readlines()) 
  except: 
    print 'error occurs while reading file'
  finally: 
    f.close()

那么, 問(wèn)題在于當(dāng)打開(kāi)文件失敗, 拋出異常將不會(huì)被捕獲.

    挫一點(diǎn)的方法自然是, 再套一層  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'

    當(dāng)然這不僅僅是多一層縮進(jìn)挫了, 連警告輸出都白白多一次呢.

    正規(guī)一點(diǎn)的方式是, 使用 Python 引入的  with  結(jié)構(gòu)來(lái)解決, 如
 

def readFile(): 
  try: 
     with open('mio', 'r') as f: 
      print ''.join(f.readlines()) 
  except: 
    print 'error occurs while reading file'

    當(dāng)文件打開(kāi)失敗時(shí), 異常自然會(huì)被  except  到; 否則, 在  with  塊結(jié)束之后, 打開(kāi)的文件將自動(dòng)關(guān)閉.

    除了打開(kāi)文件, 還有其它這樣可以用于  with  的東西么? 或者說(shuō), 怎么自定義一個(gè)什么東西, 讓它能用于  with 呢?
    直接回答后一個(gè)問(wèn)題吧, 秘密在于 Python 虛擬機(jī)在  with  塊退出時(shí)會(huì)去尋找對(duì)象的  __exit__  方法并調(diào)用它, 把釋放資源的動(dòng)作放在這個(gè)  __exit__  函數(shù)中就可以了; 另外, 對(duì)象還需要一個(gè)  __enter__  函數(shù), 當(dāng)進(jìn)入  with 塊時(shí), 這個(gè)函數(shù)被調(diào)用, 而它的返回值將作為  as  后引用的值. 一個(gè)簡(jiǎn)單的例子是
 

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!')

    執(zhí)行這一段代碼, 輸出將會(huì)是
 

init 
enter 
<type 'exceptions.ValueError'> 
kon! 
 File "test.py", line 17, in <module> 
  raise ValueError('kon!') 
 
exit

     __exit__  函數(shù)接受三個(gè)參數(shù), 分別是異常對(duì)象類(lèi)型, 異常對(duì)象和調(diào)用棧. 如果  with  塊正常退出, 那么這些參數(shù)將都是  None . 返回  True  表示發(fā)生的異常已被處理, 不再繼續(xù)向外拋出.

    簡(jiǎn)單的介紹到此為止, 詳細(xì)的情況可以參考  PEP 343  (這數(shù)字真不錯(cuò), 7 3 ).

下面介紹下 with 語(yǔ)句的實(shí)例用法 & 高級(jí)用法:

Python高端、大氣、上檔次的with語(yǔ)句

在說(shuō)with語(yǔ)句之前,先看看一段簡(jiǎn)單的代碼吧
 

lock = threading.Lock()
...
lock.acquire()
elem = heapq.heappop(heap)
lock.release()

很簡(jiǎn)單直觀,多個(gè)線(xiàn)程共用一個(gè)優(yōu)先級(jí)隊(duì)列的時(shí)候,首先先用互斥鎖lock.acquire()把優(yōu)先級(jí)隊(duì)列鎖上,然后取元素,再然后lock.release()釋放這個(gè)鎖。

雖然看似非常符合邏輯的一個(gè)過(guò)程,但是里面隱藏著一個(gè)巨大的bug:當(dāng)heap里面沒(méi)有元素的時(shí)候,會(huì)拋出一個(gè)IndexError異常,再然后堆棧回滾,再然后lock.release()根本不會(huì)執(zhí)行,這個(gè)鎖就永遠(yuǎn)得不到釋放,因此就發(fā)生了喜聞樂(lè)見(jiàn)的死鎖問(wèn)題。這個(gè)也是很多大神們討厭異常的原因。經(jīng)典Java風(fēng)格的解決方案就是
 

lock = threading.Lock()
...
lock.acquire()
try:
  elem = heapq.heappop(heap)
finally:
  lock.release()

這個(gè)雖然可以,但是怎么看怎么dirty,和Python優(yōu)雅、簡(jiǎn)單的風(fēng)格出入很大。其實(shí),自從Python2.5開(kāi)始引入了with語(yǔ)句,一切就變得非常簡(jiǎn)單:
 

lock = threading.Lock()
...
with lock:
  elem = heapq.heappop(heap)

在此無(wú)論以何種方式離開(kāi)with語(yǔ)句的代碼塊,鎖都會(huì)被釋放。
with語(yǔ)句的設(shè)計(jì)目的就是為了使得之前需要通過(guò)try...finally解決的清理資源問(wèn)題變得簡(jiǎn)單、清晰,它的的用法是
 

with expression [as variable]:
  with-block

其中expression返回一個(gè)叫做「context manager」的對(duì)象,然后這個(gè)對(duì)象被賦給variable(如果有的話(huà))。「context manager」對(duì)象有兩個(gè)方法,分別是__enter__()和__exit__(),很明顯一個(gè)在進(jìn)入with-block時(shí)調(diào)用,一個(gè)離開(kāi)with-block的時(shí)候調(diào)用。

這樣的對(duì)象不需要自己去實(shí)現(xiàn),在Python標(biāo)準(zhǔn)庫(kù)里面很多API都是已經(jīng)實(shí)現(xiàn)了這兩個(gè)方法,最常見(jiàn)的一個(gè)例子就是讀寫(xiě)文件的open語(yǔ)句。
 

with open('1.txt', encoding = 'utf-8') as fp:
  lines = fp.readlines()

無(wú)論是正常離開(kāi)還是因?yàn)楫惓T螂x開(kāi)with語(yǔ)句塊,打開(kāi)的文件資源總是會(huì)釋放。
接下去討論一下with語(yǔ)句配合contextlib庫(kù)的一些比較實(shí)用的方法,比如需要同時(shí)打開(kāi)兩個(gè)文件,一個(gè)讀一個(gè)寫(xiě),這個(gè)時(shí)候就可以這樣寫(xiě):
 

from contextlib import nested
...
with nested(open('in.txt'), open('out.txt', 'w')) as (fp_in, fp_out):
  ...

這樣就可以省掉兩個(gè)with的語(yǔ)句的嵌套了,另外如果遇到一些還沒(méi)有支持「context manager」的API呢?比如urllib.request.urlopen(),這個(gè)返回的對(duì)象因?yàn)椴皇恰竎ontext manager」,結(jié)束的時(shí)候還需要自己去調(diào)用close方法。
類(lèi)似這種API,contextlib提供了一個(gè)叫做closing方法,它會(huì)在離開(kāi)with語(yǔ)句的時(shí)候,自動(dòng)調(diào)用對(duì)象的close方法,因此urlopen也可以這樣寫(xiě):
 

from contextlib import closing
...
with closing(urllib.request.urlopen('http://www.yahoo.com')) as f:
  for line in f:
    sys.stdout.write(line)

 用 Python 做一件很平常的事情: 打開(kāi)文件, 逐行讀入, 最后關(guān)掉文件; 進(jìn)一步的需求是, 這也許是程序中一個(gè)可選的功能, 如果有任何問(wèn)題, 比如文件無(wú)法打開(kāi), 或是讀取出錯(cuò), 那么在函數(shù)內(nèi)需要捕獲所有異常, 輸出一行警告并退出. 代碼可能一開(kāi)始看起來(lái)是這樣的
 

def read_file(): 
  try: 
    f = open('yui', 'r') 
    print ''.join(f.readlines()) 
  except: 
    print 'error occurs while reading file'
  finally: 
    f.close()

    不過(guò)這顯然無(wú)法運(yùn)作, 因?yàn)?nbsp; f  是在  try  塊中定義的, 而在  finally  中無(wú)法引用.

    如果將  f  提取到  try  塊外部, 如
 

def read_file(): 
   f = open('azusa', 'r') 
  try: 
    print ''.join(f.readlines()) 
  except: 
    print 'error occurs while reading file'
  finally: 
    f.close()

那么, 問(wèn)題在于當(dāng)打開(kāi)文件失敗, 拋出異常將不會(huì)被捕獲.

    挫一點(diǎn)的方法自然是, 再套一層  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'

    當(dāng)然這不僅僅是多一層縮進(jìn)挫了, 連警告輸出都白白多一次呢.

    正規(guī)一點(diǎn)的方式是, 使用 Python 引入的  with  結(jié)構(gòu)來(lái)解決, 如
 

def readFile(): 
  try: 
     with open('mio', 'r') as f: 
      print ''.join(f.readlines()) 
  except: 
    print 'error occurs while reading file'

    當(dāng)文件打開(kāi)失敗時(shí), 異常自然會(huì)被  except  到; 否則, 在  with  塊結(jié)束之后, 打開(kāi)的文件將自動(dòng)關(guān)閉.

    除了打開(kāi)文件, 還有其它這樣可以用于  with  的東西么? 或者說(shuō), 怎么自定義一個(gè)什么東西, 讓它能用于  with 呢?
    直接回答后一個(gè)問(wèn)題吧, 秘密在于 Python 虛擬機(jī)在  with  塊退出時(shí)會(huì)去尋找對(duì)象的  __exit__  方法并調(diào)用它, 把釋放資源的動(dòng)作放在這個(gè)  __exit__  函數(shù)中就可以了; 另外, 對(duì)象還需要一個(gè)  __enter__  函數(shù), 當(dāng)進(jìn)入  with 塊時(shí), 這個(gè)函數(shù)被調(diào)用, 而它的返回值將作為  as  后引用的值. 一個(gè)簡(jiǎn)單的例子是
 

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!')

    執(zhí)行這一段代碼, 輸出將會(huì)是
 

init 
enter 
<type 'exceptions.ValueError'> 
kon! 
 File "test.py", line 17, in <module> 
  raise ValueError('kon!') 
 
exit

     __exit__  函數(shù)接受三個(gè)參數(shù), 分別是異常對(duì)象類(lèi)型, 異常對(duì)象和調(diào)用棧. 如果  with  塊正常退出, 那么這些參數(shù)將都是  None . 返回  True  表示發(fā)生的異常已被處理, 不再繼續(xù)向外拋出.

    簡(jiǎn)單的介紹到此為止, 詳細(xì)的情況可以參考  PEP 343  (這數(shù)字真不錯(cuò), 7 3 ).

下面介紹下 with 語(yǔ)句的實(shí)例用法 & 高級(jí)用法:

Python高端、大氣、上檔次的with語(yǔ)句

在說(shuō)with語(yǔ)句之前,先看看一段簡(jiǎn)單的代碼吧
 

lock = threading.Lock()
...
lock.acquire()
elem = heapq.heappop(heap)
lock.release()

很簡(jiǎn)單直觀,多個(gè)線(xiàn)程共用一個(gè)優(yōu)先級(jí)隊(duì)列的時(shí)候,首先先用互斥鎖lock.acquire()把優(yōu)先級(jí)隊(duì)列鎖上,然后取元素,再然后lock.release()釋放這個(gè)鎖。

雖然看似非常符合邏輯的一個(gè)過(guò)程,但是里面隱藏著一個(gè)巨大的bug:當(dāng)heap里面沒(méi)有元素的時(shí)候,會(huì)拋出一個(gè)IndexError異常,再然后堆?;貪L,再然后lock.release()根本不會(huì)執(zhí)行,這個(gè)鎖就永遠(yuǎn)得不到釋放,因此就發(fā)生了喜聞樂(lè)見(jiàn)的死鎖問(wèn)題。這個(gè)也是很多大神們討厭異常的原因。經(jīng)典Java風(fēng)格的解決方案就是
 

lock = threading.Lock()
...
lock.acquire()
try:
  elem = heapq.heappop(heap)
finally:
  lock.release()

這個(gè)雖然可以,但是怎么看怎么dirty,和Python優(yōu)雅、簡(jiǎn)單的風(fēng)格出入很大。其實(shí),自從Python2.5開(kāi)始引入了with語(yǔ)句,一切就變得非常簡(jiǎn)單:
 

lock = threading.Lock()
...
with lock:
  elem = heapq.heappop(heap)

在此無(wú)論以何種方式離開(kāi)with語(yǔ)句的代碼塊,鎖都會(huì)被釋放。
with語(yǔ)句的設(shè)計(jì)目的就是為了使得之前需要通過(guò)try...finally解決的清理資源問(wèn)題變得簡(jiǎn)單、清晰,它的的用法是
 

with expression [as variable]:
  with-block

其中expression返回一個(gè)叫做「context manager」的對(duì)象,然后這個(gè)對(duì)象被賦給variable(如果有的話(huà))?!竎ontext manager」對(duì)象有兩個(gè)方法,分別是__enter__()和__exit__(),很明顯一個(gè)在進(jìn)入with-block時(shí)調(diào)用,一個(gè)離開(kāi)with-block的時(shí)候調(diào)用。

這樣的對(duì)象不需要自己去實(shí)現(xiàn),在Python標(biāo)準(zhǔn)庫(kù)里面很多API都是已經(jīng)實(shí)現(xiàn)了這兩個(gè)方法,最常見(jiàn)的一個(gè)例子就是讀寫(xiě)文件的open語(yǔ)句。
 

with open('1.txt', encoding = 'utf-8') as fp:
  lines = fp.readlines()

無(wú)論是正常離開(kāi)還是因?yàn)楫惓T螂x開(kāi)with語(yǔ)句塊,打開(kāi)的文件資源總是會(huì)釋放。
接下去討論一下with語(yǔ)句配合contextlib庫(kù)的一些比較實(shí)用的方法,比如需要同時(shí)打開(kāi)兩個(gè)文件,一個(gè)讀一個(gè)寫(xiě),這個(gè)時(shí)候就可以這樣寫(xiě):
 

from contextlib import nested
...
with nested(open('in.txt'), open('out.txt', 'w')) as (fp_in, fp_out):
  ...

這樣就可以省掉兩個(gè)with的語(yǔ)句的嵌套了,另外如果遇到一些還沒(méi)有支持「context manager」的API呢?比如urllib.request.urlopen(),這個(gè)返回的對(duì)象因?yàn)椴皇恰竎ontext manager」,結(jié)束的時(shí)候還需要自己去調(diào)用close方法。
類(lèi)似這種API,contextlib提供了一個(gè)叫做closing方法,它會(huì)在離開(kāi)with語(yǔ)句的時(shí)候,自動(dòng)調(diào)用對(duì)象的close方法,因此urlopen也可以這樣寫(xiě):
 

from contextlib import closing
...
with closing(urllib.request.urlopen('http://www.yahoo.com')) as f:
  for line in f:
    sys.stdout.write(line)


相關(guān)文章

  • Python中進(jìn)程和線(xiàn)程的區(qū)別詳解

    Python中進(jìn)程和線(xiàn)程的區(qū)別詳解

    這篇文章主要介紹了Python中進(jìn)程和線(xiàn)程的區(qū)別詳解,需要的朋友可以參考下
    2017-10-10
  • python openCV獲取人臉部分并存儲(chǔ)功能

    python openCV獲取人臉部分并存儲(chǔ)功能

    這篇文章主要為大家詳細(xì)介紹了python openCV獲取人臉部分并存儲(chǔ)功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-08-08
  • Python中l(wèi)ogging日志的四個(gè)等級(jí)和使用

    Python中l(wèi)ogging日志的四個(gè)等級(jí)和使用

    這篇文章主要介紹了Python中l(wèi)ogging日志的四個(gè)等級(jí)和使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • 使用python框架Scrapy爬取數(shù)據(jù)的操作步驟

    使用python框架Scrapy爬取數(shù)據(jù)的操作步驟

    Scrapy是一個(gè)基于Python的強(qiáng)大的開(kāi)源網(wǎng)絡(luò)爬蟲(chóng)框架,用于從網(wǎng)站上抓取信息,它提供了廣泛的功能,使得爬取和分析數(shù)據(jù)變得相對(duì)容易,本文小編將給給大家介紹一下如何使用python框架Scrapy爬取數(shù)據(jù),需要的朋友可以參考下
    2023-10-10
  • Python yield 使用淺析

    Python yield 使用淺析

    這篇文章主要介紹了Python yield 使用淺析,本文給出了多個(gè)使用實(shí)例來(lái)分析yield的使用方法,需要的朋友可以參考下
    2015-05-05
  • python excel轉(zhuǎn)換csv代碼實(shí)例

    python excel轉(zhuǎn)換csv代碼實(shí)例

    這篇文章主要介紹了python excel轉(zhuǎn)換csv代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-08-08
  • Python+pandas編寫(xiě)命令行腳本操作excel的tips詳情

    Python+pandas編寫(xiě)命令行腳本操作excel的tips詳情

    這篇文章主要介紹了Python+pandas編寫(xiě)命令行腳本操作excel的tips詳情,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的朋友可以參考一下
    2022-07-07
  • Python實(shí)現(xiàn)直播彈幕自動(dòng)發(fā)送功能

    Python實(shí)現(xiàn)直播彈幕自動(dòng)發(fā)送功能

    今天制作的這一款能在B站能指定直播間、自動(dòng)發(fā)彈幕的功能的腳本,代碼也超級(jí)簡(jiǎn)單,非常適合剛剛?cè)腴T(mén)的同學(xué)進(jìn)行學(xué)習(xí),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2022-03-03
  • VScode編寫(xiě)第一個(gè)Python程序HelloWorld步驟

    VScode編寫(xiě)第一個(gè)Python程序HelloWorld步驟

    VScode是微軟去年推出的一款輕量級(jí)編輯器,功能上和Atom、Sublime Text、Vim類(lèi)似,你可以通過(guò)配置將它打造成合適的IDE,這里簡(jiǎn)單介紹一下,需要的朋友可以參考下
    2018-04-04
  • python微信公眾號(hào)之關(guān)鍵詞自動(dòng)回復(fù)

    python微信公眾號(hào)之關(guān)鍵詞自動(dòng)回復(fù)

    這篇文章主要為大家詳細(xì)介紹了python微信公眾號(hào)之關(guān)鍵詞自動(dòng)回復(fù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-06-06

最新評(píng)論