1. With operator
Reading and writing files in Python may require code like this
try-finally Read and write files
File_text = Nonetry: = open ('./text'R ') print file_text.read ()except IOError, ex: Traceback.print_exc () finally : if file_text: file_text.close ()
Similarly, using a thread lock in Python may require code like this
Try-finally Thread Lock
Lock = Threading. Lock () Lock.acquire ()try: passexcept Exception, ex: Traceback.print_exc ()finally: lock.release ()
You might find this very inconvenient, and Python provides the with operator, which you can do
With read and write files
With open ('./text'r') as File_text: Print file_text.read ()
With Thread lock
With Lock: Pass
is not much more convenient.
In fact, not only lock and file can use the with operator.
In fact, any object, as long as context management is implemented correctly, can use the WITH statement. Implementation of context management is achieved through both __enter__ and __exit__ methods.
2. Context Management
Context management can mask the complexity of the context for us. For example, we implement a class cat that implements its __enter__ and __exit__ methods.
__enter__ (self): This method is called when the context manager is entered, and its return value is placed in the variable specified by the as specifier in the With-as statement.
__exit__ (SELF,TYPE,VALUE,TB): This method is called from the context manager. If there is an exception, type, value, and TB are the exception types, values, and trace information, respectively. If there is no exception,
Each of the 3 parameters is set to none. This method returns a value of TRUE or FALSE, indicating whether the thrown exception was received or not processed. If False is returned, the thrown exception is passed out of context.
As follows.
classCat (object):def __init__(self, name): Self.name=namedef __enter__(self):Print 'enter from Cat named%s'%Self.namereturn SelfdefHello (self):Print 'Hello,%s'%Self.namedef __exit__(self, exc_type, Exc_val, EXC_TB):Print 'exit from Cat named%s'%Self.name
Execute, and print the results
With Cat ('Tom') as Tom: from from cat named Tom
Here we execute as Tom obtains an instance of the Cat class, which is obtained by the return of the __enter__ method.
Of course, we can manage multiple, please note the order of entry and exit.
With Cat ('Tom') as Tom, Cat ('Harry') as Harry: Tom.hello () fromand from Cat named Tom
3, ContextManager
Maybe you still find it troublesome to realize __enter__ and __exit__. Python provides the Contextlib.contextmanager
Let's rewrite the example above, using ContextManager
from Import ContextManager as _contextmanager@_contextmanager def Cat (name): Print ' Enter cat named%s ' % name yield name print'exit cat Named%s' % name
Execute, and print the results
With Cat ('kitty') as Kitty: print'Hello,%s ' % kittyenter cat named Kittyhello, Kittyexit cat named Kitty
The instance after as is returned by the yield statement. Here is the return of a string.
Of course, managing multiple instances is also supported
With Cat ('kitty') as Kitty, Cat ('Tom') as Tom: Print ' Hello,%s ' % kitty print'Hello,%s' % tomenter Cat named Kittyenter cat named Tomhello, Kittyhello, Tomexit cat named Tomexit cat named Kitty
4, finally give an example
Implementing Redis distributed locks using the online text manager
ImportRedisImport TimeImportThreadingImportTraceback fromContextlibImportContextManager as _contextmanagerr= Redis. Redis (host='localhost', port=6379, db=0) @_contextmanagerdefdist_lock (client, key): Dist_lock_key='lock:%s'%KeyTry: _acquire_lock (client, Dist_lock_key)yield_release_lock (client, Dist_lock_key)exceptException, ex:Passdef_acquire_lock (client, key): Is_lock= R.set (key, 1, Nx=true, ex=10) if notIs_lock:RaiseException ("already locked!")def_release_lock (client, key): Client.delete (key)deffunc (): while1: Try: With Dist_lock (R,"Key"): Print "*"Time.sleep (8) exceptException, ex:Passthread_list=list () forIinchRange (10): Thread_list.append (Threading. Thread (Target=func)) forThreadinchThread_list:thread.start () forThreadinchThread_list:thread.join ()
Python Contextlib context Manager