Python tricks(4) -- with statement

簡介html

with是從2.5版本引入的一個語法. 這個語法自己是爲了解決try..finally繁瑣的釋放各種資源(文件句柄, Lock等)的問題.python

若是想在舊版本中使用這個功能, 直接引入future模塊就能夠.c++

from __future__ import with_statement

舉例簡單說明一下沒有with和有with的代碼區別sql

try:
    dict_file = open("dict_file_path")
    for line in dict_file:
        print line,  # do something
finally:
    dict_file.close()

用with-statement的方式以下數據庫

with open("dict_file_path") as dict_file:
    for line in dict_file:
        print line,  # do something

明顯使用了with以後語法更加簡潔.express

官方對於with-statement的定義以下session

with_stmt ::=  "with" with_item ("," with_item)* ":" suite
with_item ::=  expression ["as" target]

從定義中, 咱們能夠看出, 若是想經過with使用多個資源的話, 能夠使用下面的寫法app

with open("d1_file") as d1, open("d2_file") as d2:

as部分是無關緊要的, 對於lock等這類資源來講通常都是這種用法函數

我的認爲, with-statement是如今帶有內存管理語言的折中處理方法, 對於c++來講, 能夠使用RAII的方式, 一個類有明確的析構函數, 在超出做用域以後會被調用, 在析構函數內進行資源的釋放是很是不錯的選擇. 也體現了c++的高效, 靈活和優雅.性能

Java, python這類語言都沒法作到, 可是語言自身的異常機制都很是完善, 不像c++爲了兼容c致使異常機制顯得有點雞肋. try..catch..finally就成爲了這類語言用來進行資源釋放的方式, GC(垃圾回收)回收內存的時間不肯定, 沒法利用RAII.

 

With-statement Magic Method

python語言層面上對於with的支持是經過magic method來實現的, 和通常的python特性同樣.

使用PEP343中with-statement的定義來引入這兩個magic method

with VAR = EXPR:
        BLOCK

直接翻譯過來就是

VAR = EXPR
VAR.__enter__()
try:
        BLOCK
finally:
        VAR.__exit__()

咱們能夠清楚的看到這兩個magic method分別是__enter__和__exit__, 一個在進入with-statement block的時候初始化, 一個在離開的時候進行cleanup工做.

下面來舉一個簡單的timer例子.

import time

class Timer(object):
    def __init__(self):
        pass

    def __enter__(self):
        self.start = time.time()

    def __exit__(self, exception_type, exception_val, trace):
        print "elapsed:", time.time() - self.start

if __name__ == "__main__":
    with Timer():
        [i for i in xrange(10000000)]

運行結果以下:

elapsed: 1.32907581329

timer是一個簡單實用的類, 在編寫性能測試代碼的時候, 常常會用到.

水平有限, 歡迎拍磚!

 

2014.4.19 添加一個with帶有異常處理的demo

 以一個操做數據庫的session爲例, 下面的方式能夠替代繁瑣的try...except...finally語句, 能夠包裝sqlalchemy的session.

筆者用這個簡單的封裝做爲sqlalchemy來方便處理session相關的操做. commit操做須要本身去調用, 也能夠加入到exit方法中.

class Wrapper(object):
    '''A context manager to automatically close an object with a close method
    in a with statement.'''

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

    def __enter__(self):
        return self.obj  # bound to target

    def __exit__(self, exception_type, exception_val, trace):
        if exception_type:
            try:
                self.obj.rollback()
            except AttributeError:  # obj cannot rollback
                return True  # exception handled successfully
        try:
            self.obj.close()
        except AttributeError:  # obj isn't closable
            return True  # exception handled successfully    

  

 

參考文獻:

  1. PEP343: http://www.python.org/dev/peps/pep-0343/
  2. Python Docs <Compound statements>: http://docs.python.org/2/reference/compound_stmts.html#the-with-statement
相關文章
相關標籤/搜索