国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

腳本之家,腳本語言編程技術及教程分享平臺!
分類導航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

香港云服务器
服務器之家 - 腳本之家 - Python - 簡單介紹Python中的try和finally和with方法

簡單介紹Python中的try和finally和with方法

2020-06-22 10:01xrzs Python

這篇文章主要介紹了Python中的try和finally和with方法,是Python學習當中的基礎知識,需要的朋友可以參考下

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

?
1
2
3
4
5
6
7
8
def read_file():
  try:
    f = open('yui', 'r')
    print ''.join(f.readlines())
  except:
    print 'error occurs while reading file'
  finally:
    f.close()

    不過這顯然無法運作, 因為  f  是在  try  塊中定義的, 而在  finally  中無法引用.

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

?
1
2
3
4
5
6
7
8
def read_file():
   f = open('azusa', 'r')
  try:
    print ''.join(f.readlines())
  except:
    print 'error occurs while reading file'
  finally:
    f.close()

那么, 問題在于當打開文件失敗, 拋出異常將不會被捕獲.

    挫一點的方法自然是, 再套一層  try  吧
 

?
1
2
3
4
5
6
7
8
9
10
11
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'

    當然這不僅僅是多一層縮進挫了, 連警告輸出都白白多一次呢.

    正規一點的方式是, 使用 Python 引入的  with  結構來解決, 如
 

?
1
2
3
4
5
6
def readFile():
  try:
     with open('mio', 'r') as f:
      print ''.join(f.readlines())
  except:
    print 'error occurs while reading file'

    當文件打開失敗時, 異常自然會被  except  到; 否則, 在  with  塊結束之后, 打開的文件將自動關閉.

    除了打開文件, 還有其它這樣可以用于  with  的東西么? 或者說, 怎么自定義一個什么東西, 讓它能用于  with 呢?
    直接回答后一個問題吧, 秘密在于 Python 虛擬機在  with  塊退出時會去尋找對象的  __exit__  方法并調用它, 把釋放資源的動作放在這個  __exit__  函數中就可以了; 另外, 對象還需要一個  __enter__  函數, 當進入  with 塊時, 這個函數被調用, 而它的返回值將作為  as  后引用的值. 一個簡單的例子是
 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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!')

    執行這一段代碼, 輸出將會是
 

?
1
2
3
4
5
6
7
8
init
enter
<type 'exceptions.ValueError'>
kon!
 File "test.py", line 17, in <module>
  raise ValueError('kon!')
 
exit

     __exit__  函數接受三個參數, 分別是異常對象類型, 異常對象和調用棧. 如果  with  塊正常退出, 那么這些參數將都是  None . 返回  True  表示發生的異常已被處理, 不再繼續向外拋出.

    簡單的介紹到此為止, 詳細的情況可以參考  PEP 343  (這數字真不錯, 7 3 ).

下面介紹下 with 語句的實例用法 & 高級用法:

Python高端、大氣、上檔次的with語句

在說with語句之前,先看看一段簡單的代碼吧
 

?
1
2
3
4
5
lock = threading.Lock()
...
lock.acquire()
elem = heapq.heappop(heap)
lock.release()

很簡單直觀,多個線程共用一個優先級隊列的時候,首先先用互斥鎖lock.acquire()把優先級隊列鎖上,然后取元素,再然后lock.release()釋放這個鎖。

雖然看似非常符合邏輯的一個過程,但是里面隱藏著一個巨大的bug:當heap里面沒有元素的時候,會拋出一個IndexError異常,再然后堆棧回滾,再然后lock.release()根本不會執行,這個鎖就永遠得不到釋放,因此就發生了喜聞樂見的死鎖問題。這個也是很多大神們討厭異常的原因。經典Java風格的解決方案就是
 

?
1
2
3
4
5
6
7
lock = threading.Lock()
...
lock.acquire()
try:
  elem = heapq.heappop(heap)
finally:
  lock.release()

這個雖然可以,但是怎么看怎么dirty,和Python優雅、簡單的風格出入很大。其實,自從Python2.5開始引入了with語句,一切就變得非常簡單:
 

?
1
2
3
4
lock = threading.Lock()
...
with lock:
  elem = heapq.heappop(heap)

在此無論以何種方式離開with語句的代碼塊,鎖都會被釋放。
with語句的設計目的就是為了使得之前需要通過try...finally解決的清理資源問題變得簡單、清晰,它的的用法是
 

?
1
2
with expression [as variable]:
  with-block

其中expression返回一個叫做「context manager」的對象,然后這個對象被賦給variable(如果有的話)。「context manager」對象有兩個方法,分別是__enter__()和__exit__(),很明顯一個在進入with-block時調用,一個離開with-block的時候調用。

這樣的對象不需要自己去實現,在Python標準庫里面很多API都是已經實現了這兩個方法,最常見的一個例子就是讀寫文件的open語句。
 

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

無論是正常離開還是因為異常原因離開with語句塊,打開的文件資源總是會釋放。
接下去討論一下with語句配合contextlib庫的一些比較實用的方法,比如需要同時打開兩個文件,一個讀一個寫,這個時候就可以這樣寫:
 

?
1
2
3
4
from contextlib import nested
...
with nested(open('in.txt'), open('out.txt', 'w')) as (fp_in, fp_out):
  ...

這樣就可以省掉兩個with的語句的嵌套了,另外如果遇到一些還沒有支持「context manager」的API呢?比如urllib.request.urlopen(),這個返回的對象因為不是「context manager」,結束的時候還需要自己去調用close方法。
類似這種API,contextlib提供了一個叫做closing方法,它會在離開with語句的時候,自動調用對象的close方法,因此urlopen也可以這樣寫:
 

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

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

?
1
2
3
4
5
6
7
8
def read_file():
  try:
    f = open('yui', 'r')
    print ''.join(f.readlines())
  except:
    print 'error occurs while reading file'
  finally:
    f.close()

    不過這顯然無法運作, 因為  f  是在  try  塊中定義的, 而在  finally  中無法引用.

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

?
1
2
3
4
5
6
7
8
def read_file():
   f = open('azusa', 'r')
  try:
    print ''.join(f.readlines())
  except:
    print 'error occurs while reading file'
  finally:
    f.close()

那么, 問題在于當打開文件失敗, 拋出異常將不會被捕獲.

    挫一點的方法自然是, 再套一層  try  吧
 

?
1
2
3
4
5
6
7
8
9
10
11
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'

    當然這不僅僅是多一層縮進挫了, 連警告輸出都白白多一次呢.

    正規一點的方式是, 使用 Python 引入的  with  結構來解決, 如
 

?
1
2
3
4
5
6
def readFile():
  try:
     with open('mio', 'r') as f:
      print ''.join(f.readlines())
  except:
    print 'error occurs while reading file'

    當文件打開失敗時, 異常自然會被  except  到; 否則, 在  with  塊結束之后, 打開的文件將自動關閉.

    除了打開文件, 還有其它這樣可以用于  with  的東西么? 或者說, 怎么自定義一個什么東西, 讓它能用于  with 呢?
    直接回答后一個問題吧, 秘密在于 Python 虛擬機在  with  塊退出時會去尋找對象的  __exit__  方法并調用它, 把釋放資源的動作放在這個  __exit__  函數中就可以了; 另外, 對象還需要一個  __enter__  函數, 當進入  with 塊時, 這個函數被調用, 而它的返回值將作為  as  后引用的值. 一個簡單的例子是
 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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!')

    執行這一段代碼, 輸出將會是
 

?
1
2
3
4
5
6
7
8
init
enter
<type 'exceptions.ValueError'>
kon!
 File "test.py", line 17, in <module>
  raise ValueError('kon!')
 
exit

     __exit__  函數接受三個參數, 分別是異常對象類型, 異常對象和調用棧. 如果  with  塊正常退出, 那么這些參數將都是  None . 返回  True  表示發生的異常已被處理, 不再繼續向外拋出.

    簡單的介紹到此為止, 詳細的情況可以參考  PEP 343  (這數字真不錯, 7 3 ).

下面介紹下 with 語句的實例用法 & 高級用法:

Python高端、大氣、上檔次的with語句

在說with語句之前,先看看一段簡單的代碼吧
 

?
1
2
3
4
5
lock = threading.Lock()
...
lock.acquire()
elem = heapq.heappop(heap)
lock.release()

很簡單直觀,多個線程共用一個優先級隊列的時候,首先先用互斥鎖lock.acquire()把優先級隊列鎖上,然后取元素,再然后lock.release()釋放這個鎖。

雖然看似非常符合邏輯的一個過程,但是里面隱藏著一個巨大的bug:當heap里面沒有元素的時候,會拋出一個IndexError異常,再然后堆棧回滾,再然后lock.release()根本不會執行,這個鎖就永遠得不到釋放,因此就發生了喜聞樂見的死鎖問題。這個也是很多大神們討厭異常的原因。經典Java風格的解決方案就是
 

?
1
2
3
4
5
6
7
lock = threading.Lock()
...
lock.acquire()
try:
  elem = heapq.heappop(heap)
finally:
  lock.release()

這個雖然可以,但是怎么看怎么dirty,和Python優雅、簡單的風格出入很大。其實,自從Python2.5開始引入了with語句,一切就變得非常簡單:
 

?
1
2
3
4
lock = threading.Lock()
...
with lock:
  elem = heapq.heappop(heap)

在此無論以何種方式離開with語句的代碼塊,鎖都會被釋放。
with語句的設計目的就是為了使得之前需要通過try...finally解決的清理資源問題變得簡單、清晰,它的的用法是
 

?
1
2
with expression [as variable]:
  with-block

其中expression返回一個叫做「context manager」的對象,然后這個對象被賦給variable(如果有的話)。「context manager」對象有兩個方法,分別是__enter__()和__exit__(),很明顯一個在進入with-block時調用,一個離開with-block的時候調用。

這樣的對象不需要自己去實現,在Python標準庫里面很多API都是已經實現了這兩個方法,最常見的一個例子就是讀寫文件的open語句。
 

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

無論是正常離開還是因為異常原因離開with語句塊,打開的文件資源總是會釋放。
接下去討論一下with語句配合contextlib庫的一些比較實用的方法,比如需要同時打開兩個文件,一個讀一個寫,這個時候就可以這樣寫:
 

?
1
2
3
4
from contextlib import nested
...
with nested(open('in.txt'), open('out.txt', 'w')) as (fp_in, fp_out):
  ...

這樣就可以省掉兩個with的語句的嵌套了,另外如果遇到一些還沒有支持「context manager」的API呢?比如urllib.request.urlopen(),這個返回的對象因為不是「context manager」,結束的時候還需要自己去調用close方法。
類似這種API,contextlib提供了一個叫做closing方法,它會在離開with語句的時候,自動調用對象的close方法,因此urlopen也可以這樣寫:
 

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

延伸 · 閱讀

精彩推薦
682
主站蜘蛛池模板: 欧美午夜一区二区福利视频 | 国产一区二区av在线 | 中文字幕亚洲欧美 | 日韩一区二区三区在线观看 | 国产精品999 | 免费av在线 | 亚洲免费观看视频 | 亚洲免费视频观看 | 日韩在线播放一区二区三区 | 天天干天天干天天干天天射 | 免费看黄色的视频 | 久久青青 | 亚洲精品国产精品国自产在线 | 国产精品久久久久久中文字 | 韩日av在线| 91在线免费视频 | 欧美狠狠干| 国产午夜精品一区二区三区嫩草 | 91亚洲精品在线 | 亚洲午夜一区 | 九一视频在线免费观看 | 精品久久久久久久中文字幕 | 黄色短片免费看 | 欧美福利 | 国产精品网站在线观看 | 91色在线观看 | 中文字幕国产视频 | 日韩a电影 | 天天操天天添 | 欧美一区二区三区不卡 | 一区二区三区精品 | 亚洲午夜精品视频 | 久久精品国产一区二区三区不卡 | 精品久久久久久国产 | 亚洲国产精品久久 | 毛片一级在线观看 | 久久久激情 | 国产精品久久久久久久久久久久久 | 欧美在线观看www | 中文字幕亚洲一区二区三区 | 国产高清一级片 |