Python中的with用法

2021-09-30 17:22:11 字數 3897 閱讀 1223

原文出處:

有一些任務,可能事先需要設定,事後做清理工作。對於這種場景,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語句提供了一種非常方便的處理方式。其中乙個很好的例子是檔案處理,你需要獲取乙個檔案控制代碼,從檔案中讀取資料,然後關閉檔案控制代碼...