原文出處:
有一些任務,可能事先需要設定,事後做清理工作。對於這種場景,python的with語句提供了一種非常方便的處理方式。乙個很好的例子是檔案處理,你需要獲取乙個檔案控制代碼,從檔案中讀取資料,然後關閉檔案控制代碼。
如果不用with語句,**如下:
file =
open
("/tmp/foo.txt"
)data = file.
read()
file.
close
()
這裡有兩個問題:
一是可能忘記關閉檔案控制代碼;
二是檔案讀取資料發生異常,沒有進行任何處理。
下面是處理異常的加強版本:
try
: f =
open
('***'
)except:
print 'fail to open'
exit(-
1)try:
do something
except:
do something
finally
: f.
close
()
雖然這段**執行良好,但是太冗長了。
這時候就是with一展身手的時候了。除了有更優雅的語法,with還可以很好的處理上下文環境產生的異常。
下面是with版本的**:
with
open
("/tmp/foo.txt"
)as file:
data = file.
read
()
下面例子可以具體說明with如何工作:
#!
/usr/bin/env python
# with_example01.py
class
sample
: def __enter__
(self)
: print "in __enter__()"
return
"foo"
def __exit__
(self, type, value, trace)
: print "in __exit__()"
def get_sample()
:return
sample()
with
get_sample()
as sample:
print "sample:"
, sample
執行**,輸出如下
bash-
3.2$ .
/with_example01.py
in __enter__()
sample: foo
in __exit__
()
正如你看到的: 1. __enter__()方法被執行 2. __enter__()方法返回的值 - 這個例子中是」foo」,賦值給變數』sample』 3. 執行**塊,列印變數」sample」的值為 「foo」 4. __exit__()方法被呼叫 with真正強大之處是它可以處理異常。
可能你已經注意到sample類的 __exit__ 方法有三個引數 val, type 和 trace。 這些引數在異常處理中相當有用。我們來改一下**,看看具體如何工作的。
#!
/usr/bin/env python
# with_example02.py
class
sample
: def __enter__
(self)
:return self
def __exit__
(self, type, value, trace)
: print "type:"
, type
print "value:"
, value
print "trace:"
, trace
def do_something
(self)
: bar =1/
0return bar +
10with
sample()
as sample:
sample.
do_something
()
這個例子中,with後面的get_sample()變成了sample()。這沒有任何關係,只要緊跟with後面的語句所返回的物件有 __enter__() 和 __exit__() 方法即可。此例中,sample()的 __enter__() 方法返回新建立的sample物件,並賦值給變數sample。
**執行後:
bash-
3.2$ .
/with_example02.py
type:
>
value: integer division or modulo by zero
trace:
>
traceback
(most recent call last)
: file "./with_example02.py"
, line 19,in
sample.
do_something()
file "./with_example02.py"
, line 15
,in do_something
bar =1/
0zerodivisionerror: integer division or modulo by zero
實際上,在with後面的**塊丟擲任何異常時,__exit__() 方法被執行。正如例子所示,異常丟擲時,與之關聯的type,value和stack trace傳給 __exit__() 方法,因此丟擲的zerodivisionerror異常被列印出來了。開發庫時,清理資源,關閉檔案等等操作,都可以放在 __exit__ 方法當中。
另外,__exit__ 除了用於tear things down,還可以進行異常的監控和處理,注意後幾個引數。要跳過乙個異常,只需要返回該函式true即可。
下面的樣例**跳過了所有的typeerror,而讓其他異常正常丟擲。
def __exit__
(self, type, value, traceback)
:return
isinstance
(value, typeerror)
上文說了 __exit__ 函式可以進行部分異常的處理,如果我們不在這個函式中處理異常,他會正常丟擲,這時候我們可以這樣寫(python 2.7及以上版本,之前的版本參考使用contextlib.nested這個庫函式):
try
:with
open
("a.txt"
)as f :
do something
except ***error:
do something about exception
總之,with-as表示式極大的簡化了每次寫finally的工作,這對保持**的優雅性是有極大幫助的。
如果有多個項,我們可以這麼寫:
with
open
("x.txt"
)as f1,
open
('***.txt'
)as f2:
do something with f1,f2
因此,python的with語句是提供乙個有效的機制,讓**更簡練,同時在異常產生時,清理工作更簡單。 python中with的用法
剛剛開始學python,今天在乙個基礎例子中看到了一行 覺得很有意思,就去研究了一下 with open config name login.txt r as f 其實這是python中的with語句,類似於php中的try catch 主要是用來檔案處理,你需要的是獲取乙個檔案控制代碼,然後從檔案...
python中with的用法
python中with的用法 清單 1.with 語句的語法格式 1 2 with context expression as target s with body 無論context expression是否發生異常,都能保證不報錯,類似於try finally正規化。enter 語句返回值賦給t...
Python中with的用法
之前再遇到with語句在檔案操作上的用法非常巧妙,以前不太熟悉,看的時候也產生一些困惑 有一些任務,可能事先需要設定,事後做清理工作。對於這種場景,python的with語句提供了一種非常方便的處理方式。其中乙個很好的例子是檔案處理,你需要獲取乙個檔案控制代碼,從檔案中讀取資料,然後關閉檔案控制代碼...