2012年8月11日 星期六

with 與 __enter__(),__exit__(),上下文管理器



class Context(object):
    def __init__(self): #物件初始化時執行此方法
        print '__init__()'
    def __enter__(self):#進入with區塊後執行此方法
        print '__enter__()'
        return self
    def __exit__(self, exc_type, exc_val,exc_tb):#離開敘述區塊執行此方法
        print '__exit__()'

with Context():
    print 'Doing work in the context' #敘述區塊



執行結果
>>> 
__init__()
__enter__()
Doing work in the context
__exit__()
_________________________________________________________________

class WithinHello(object):
    def __init__(self, context):
        print 'WithinHello.__init__(%s)' %context
    def do_something(self):
        print 'WithinHello.do_something()'
    def __del__(self):
        print 'WithinHello.__del__'

class Hello(object):
    def __init__(self):
        print 'Hello.__init__()'
    def __enter__(self):
        print 'Hello.__enter__()'
        return WithinHello(self)
    def __exit__(self, exc_type, exc_val,exc_tb):
        print 'Hello.__exit__()'
  
with Hello() as c:
    c.do_something() #此時c為WithinHello的物件





>>>
Hello.__init__()
Hello.__enter__()
WithinHello.__init__(<__main__.Hello object at 0x0000000001CF9FD0>)
WithinHello.do_something()
Hello.__exit__()

_________________________________________________________________

class Context(object):
    def __init__(self, handle_error):
        print '__init__(%s)' % handle_error
        self.handle_error = handle_error
    def __enter__(self):
        print '__enter__()'
        return self
    def __exit__(self, exc_type, exc_val,exc_tb):
        print '__exit__()'
        print ' exc_type =', exc_type
        print ' exc_val  =', exc_val
        print ' exc_tb   =', exc_tb
        return self.handle_error 
        #如果上下文管理器可以處理這個異常,__exit__() 應當返回一個true值來指示不需要傳播這個異       常。如果返回false,就會導致__exit__()返回後重新拋出這個異常。

with Context(True):
    raise RuntimeError('error message handled')
print

with Context(False):
    raise RuntimeError('error message propagated')




>>> 
__init__(True)
__enter__()
__exit__()
 exc_type = <type 'exceptions.RuntimeError'>
 exc_val  = error message handled
 exc_tb   = <traceback object at 0x0000000002AB5B48>

__init__(False)
__enter__()
__exit__()
 exc_type = <type 'exceptions.RuntimeError'>
 exc_val  = error message propagated
 exc_tb   = <traceback object at 0x0000000002AB5D08>

Traceback (most recent call last):
  File "D:/python26/contextErrorHandle.py", line 20, in <module>
    raise RuntimeError('error message propagated')
RuntimeError: error message propagated
_________________________________________________________________

總和所有重要功能的程式碼


#-*- coding:utf8 -*-
#myContextManager.py

class withinContext(object):
    def __init__(self,context):
        #必定需要使用兩個參數self,context
        #其中withinContext中__init__方法的context參數用以接收
        #myContext中__enter__方法的return withinContext(self)敘述式的self參數
        print 'withinContext.__init__(%s)'%context
    def __del__(self):
        print 'withinContext.__del__()'
    def do_something(self):
        print 'withinContext.do_something()'

class myContext(object):
    def __init__(self,handle_error):
        print "myContext.__init__(%s)"%handle_error
        self.handle_error = handle_error
    def __enter__(self):
        print "myContext.__enter__()"
        return withinContext(self)
    def __exit__(self, exc_type, exc_val,exc_tb): #必定需要使用四個參數self,exc_type,exc_val,exc_tb
        print "myContext.__exit__()"
        print "exc_type:",exc_type
        print "exc_val :",exc_val
        print "exc_tb  :",exc_tb
        return self.handle_error #__exit__()方法若回傳True代表不傳播異常 若回傳False則代表傳播異常


with myContext(True) as c:
    c.do_something()
    raise RuntimeError('error message propagated.')



沒有留言:

張貼留言