python 上下文管理器contextlib.ContextManager

1 模塊簡介

在數年前,Python 2.5 加入了一個很是特殊的關鍵字,就是with。with語句容許開發者建立上下文管理器。什麼是上下文管理器?上下文管理器就是容許你能夠自動地開始和結束一些事情。例如,你可能想要打開一個文件,而後寫入一些內容,最後再關閉文件。這或許就是上下文管理器中一個最經典的示例。事實上,當你利用with語句打開一個文件時,Python替你自動建立了一個上下文管理器。html

with open("test/test.txt","w") as f_obj:
    f_obj.write("hello")

若是你使用的是Python 2.4,你不得不以一種老的方式來完成這個任務sql

f_obj = open("test/test.txt","w")
f_obj.write("hello")
f_obj.close()

下文管理器背後工做的機制是使用Python的方法:__enter__和__exit__。讓咱們嘗試着去建立咱們的上下文管理器,以此來了解上下文管理器是如何工做的。數據庫

2 模塊使用

2.0 一個簡單的demo

import contextlib
import time

@contextlib.contextmanager
def timeit(title):
    print('1...')
    start = time.time()
    yield
    print('2...')
    end = time.time()
    usedTime = (end - start) * 1000
    print('Use time %d ms' % usedTime)


with timeit(1):
    print('3...')
    time.sleep(1)

with timeit(2):
    print('4...')
    time.sleep(2)

輸出結果:函數

1...
3...
2...
Use time 1001 ms
1...
4...
2...
Use time 2002 ms

 

2.1 建立一個上下文管理器類

與其繼續使用Python打開文件這個例子,不如咱們建立一個上下文管理器,這個上下文管理器將會建立一個SQLite數據庫鏈接,當任務處理完畢,將會將其關閉。下面就是一個簡單的示例。spa

import sqlite3

class DataConn:
    def __init__(self,db_name):
        self.db_name = db_name

    def __enter__(self):
        self.conn = sqlite3.connect(self.db_name)
        return self.conn

    def __exit__(self,exc_type,exc_val,exc_tb):
        self.conn.close()
        if exc_val:
            raise

if __name__ == "__main__":
    # with 裝飾器的底層原理其實是__enter__和__exit__  實現的。
    db = "test/test.db"
    with DataConn(db) as conn:
        cursor = conn.cursor()

2.2 利用contextlib建立一個上下文管理器

Python 2.5 不單單添加了with語句,它也添加了contextlib模塊。這就容許咱們使用contextlib的contextmanager函數做爲裝飾器,來建立一個上下文管理器。讓咱們嘗試着用它來建立一個上下文管理器,用於打開和關閉文件code

from contextlib import contextmanager

@contextmanager
def file_open(path):
    try:
        f_obj = open(path,"w")
        yield f_obj
    except OSError:
        print("We had an error!")
    finally:
        print("Closing file")
        f_obj.close()

if __name__ == "__main__":
    with file_open("test/test.txt") as fobj:
        fobj.write("Testing context managers")

原文連接sqlite

相關文章
相關標籤/搜索