python 的with
語句支援通過上下文管理器
所定義的執行時上下文這一概念。
此物件的實現使用了一對專門方法,允許使用者自定義類來定義執行時上下文,在語句體被執行前進入該上下文,並在語句執行完畢時退出該上下文。
例如,檔案物件的快速開啟和關閉:
with
open
(file_path,
'r', encoding=
'utf8'
)as f:
for line in f:..
..
上下文管理器
是乙個物件,它定義了在執行with
語句時要建立的執行時上下文。
上下文管理器處理進入(enter
)和退出(exit
)所需執行時上下文以執行**塊。
進入執行時
上下文並返回此物件或關聯到該執行時上下文的其他物件。
此方法的返回值
會繫結到使用此上下文管理器的with
語句的as
子句中的識別符號
退出執行時
上下文並返回乙個布林值旗標來表明所發生的任何異常是否應當被遮蔽。
如果在執行with
語句的語句體期間發生了異常,則引數會包含異常的型別、值以及回溯資訊
import time
class
runtime
:def
__init__
(self, event)
: self.event = event
def__enter__
(self)
: self.start = time.time(
)def
__exit__
(self, exc_ty, exc_val, exc_tb)
: self.end = time.time(
)print
('function:{},used time:{}s'
.format
(self.event, self.end - self.start)
)
可用於統計函式執行的時長
>>
>
with runtime(
'test'):
... a =0.
..for _ in
range
(10000):
... a +=
1function:test,used time:
0.0009884834289550781s
編寫上下文管理器的主要原理是你的**會放到with
語句塊中執行。
當出現with
語句的時候,物件的__enter__()
方法被觸發, 它返回的值(如果有的話)會被賦值給as
宣告的變數。然後,with
語句塊裡面的**開始執行。 最後,__exit__()
方法被觸發進行清理工作。
不管with
**塊中發生什麼,上面的控制流都會執行完,就算**塊中發生了異常也是一樣的。
事實上,__exit__()
方法的三個引數包含了異常型別、異常值和追溯資訊(如果有的話)
。
__exit__()
方法能自己決定怎樣利用這個異常資訊,或者忽略它並返回乙個none
值。
如果__exit__()
返回true
,那麼異常會被清空,就好像什麼都沒發生一樣,with
語句後面的程式繼續在正常執行。
在需要管理一些資源比如檔案、網路連線和鎖的程式設計環境中,使用上下文管理器是很普遍的。
這些資源的乙個主要特徵是它們必須被手動地關閉或釋放來確保程式的正確執行。 例如,如果你請求了乙個鎖,那麼你必須確保之後釋放了它,否則就可能產生死鎖。 通過實現__enter__()
和__exit__()
方法並使用with
語句可以很容易的避免這些問題, 因為__exit__()
方法可以讓你無需擔心這些了。
實現乙個新的上下文管理器的最簡單的方法就是使用contexlib
模組中的@contextmanager
裝飾器。
import time
from contextlib import contextmanager
@contextmanager
defrun_time
(event)
: start = time.time(
)try
:yield
finally
: end = time.time(
)print
('function:{},used time:{}s'
.format
(event, end - start)
)
在函式run_time()
中,yield
之前的**會在上下文管理器中作為 __enter__() 方法執行, 所有在yield
之後的**會作為 __exit__() 方法執行。 如果出現了異常,異常會在yield
語句那裡丟擲。
下面是乙個更加高階一點的上下文管理器
@contextmanager
defsession_maker
(_session=session)
:try
:yield _session
_session.commit(
)except exception as e:
_session.rollback(
)print
('error'
, e)
finally
: _session.close(
)
每次呼叫,session自動commit和關閉,保證資料的安全和完整
from contextlib import contextmanager
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
db_config=
base = declarative_base(
)engine = create_engine(
'mysql+pymysql://:@:/'
.format
(**db_config)
, encoding=
'utf-8'
, echo=
false,)
session = sessionmaker(bind=engine)
session = session(
)@contextmanager
defsession_maker
(_session=session)
:try
:yield _session
_session.commit(
)except exception as e:
_session.rollback(
)print
('error'
, e)
finally
: _session.close(
)if __name__ ==
'__main__'
:with session_maker(
)as db_session:
result = db_session.query(model)
.all()
...
python with上下文管理
class person def init self,name self name name def enter self print 這是with定義的物件進到了enter方法中執行操作 return self def exit self,exc type,exc value,exc tb pri...
Python with語句和上下文管理器物件
今天看書,書上面提到要盡量使用with自動關閉資源,裡面還提到了上下文管理器物件的概念,然後查詢資料,對with的解釋如下 with的有一些任務,可能事先需要設定,事後做清理工作。對於這種場景,python的with語句提供了一種非常方便的處理方式。乙個很好的例子是檔案處理,需要獲取乙個檔案控制代碼...
Python with及上下文管理器的原理和應用
with 語句是 pyhton 提供的一種簡化語法,適用於對資源進行訪問的場合,確保不管使用過程中是否發生異常都會執行必要的 清理 操作,釋放資源,with 語句主要是為了簡化 操作。with 檔案使用後自動關閉 建立乙個檔案test.txt,若存在則開啟,寫入hello python 建立 開啟檔...