1. 程式人生 > 程式設計 >Python上下文管理器全例項詳解

Python上下文管理器全例項詳解

Python上下文管理器

簡介

最近用到這個,仔細瞭解了一下,感覺是十分有用的,記錄一下

使用場景

當我們需要獲取一個臨時開啟的資源,並在使用完畢後進行資源釋放和異常處理,利用try-catch語句可以完成,舉個例子。

開啟檔案:

f = None
try:
 print("try")
 f = open("__init__.py","r")
 print(f.read())
except Exception as e:
 print("exception")
finally:
 if f:
  print("finally")
  f.close()

利用上下文管理器:

class OpenHandle:

 def __init__(self,filename,mode):
  self.filename = filename
  self.mode = mode

 def __enter__(self):
  self.f = open(self.filename,self.mode)
  return self.f

 def __exit__(self,exc_type,exc_val,exc_tb):
  if exc_type:
   print("exception")
  else:
   print("normal")
  self.f.close()

with OpenHandle("book.txt","r") as f:
 print(f.read())

這樣可以利用with-as語句改寫程式碼,讓程式設計師關注業務主流程,去掉對於資源的獲取和關閉這些重複操作。提升程式碼的可讀性。好處很大。

執行順序

執行順序是理解這種寫法的關鍵:

  • 初始化,執行handle的__init__()
  • __enter__()方法,獲取資源物件,返回給as後的變數
  • 業務程式碼邏輯
  • __exit__方法,傳入3個引數,異常型別,異常物件,呼叫棧物件,無異常都為None
  • 丟擲異常或者正常結束

函式式上下文管理器

利用from contextlib import contextmanager這個裝飾器可以將函式裝飾為上下文管理器,其實這個裝飾背後也是返回一個實現了__enter__和__exit__方法的類

from contextlib import contextmanager

@contextmanager
def managed_resource(*args,**kwds):
 # Code to acquire resource,e.g.:
 resource = acquire_resource(*args,**kwds)
 try:
  yield resource
 finally:
  # Code to release resource,e.g.:
  release_resource(resource)

>>> with managed_resource(timeout=3600) as resource:
...  # Resource is released at the end of this block,...  # even if code in the block raises an exception

模板程式碼

sqlalchemy會話上下文管理器

利用這個管理sqlalchemy會話物件的獲取和釋放,控制事務是再合適不過了

class DbTransaction:

 def __init__(self,session_maker):
  self.session_maker = session_maker

 def __enter__(self):
  self.session = self.session_maker()
  return self.session

 def __exit__(self,exc_tb):
  if exc_type:
   self.session.rollback()
  else:
   self.session.commit()
  self.session.close()
  return False if exc_type else True

以上就是全部相關知識點,感謝大家的學習和對我們的支援。