Python With statement detailed _python

Source: Internet
Author: User
Tags commit rollback in python

First, Introduction

With is a new syntax introduced from Python 2.5, more precisely, a context management protocol that simplifies the processing of try...except...finally. With the __enter__ method to initialize, and then do the cleanup in the __exit__ and handle the exception. With some tasks that need to be set up beforehand to clean up afterwards, with provides a very convenient expression.

The basic syntax for with is as follows, expr is an arbitrary expression, VAR is a single variable (can be tuple), and "as Var" is optional.

Copy Code code as follows:

With EXPR as VAR:
Block

According to Pep 343 's explanation, with...as ... will be translated into the following statement:
Copy Code code as follows:

MGR = (EXPR)
Exit = Type (MGR). __exit__ # not calling it yet
Value = Type (MGR). __enter__ (MGR)
EXC = True
Try
Try
VAR = value # only if ' as VAR ' is present
Block
Except
# The exceptional case are handled here
EXC = False
If not exit (Mgr, *sys.exc_info ()):
Raise
# The exception is swallowed if Exit () returns True
Finally
# The normal and Non-local-goto cases are handled here
If exc:
Exit (Mgr, none, none, none)

Why is it so complicated? Note the finally code, which requires that the block be executed before the finally cleanup is performed, because when expr executes, an exception is thrown, and the access Mgr.exit execution reports a attributeerror error.


Ii. Ways of implementation

According to the previous translation of the with, we can see that the object being evaluated with must have a __enter__ method and a __exit__ method. Take a look at the example of a file read, note that here we want to solve 2 problems: File read exception, after reading, close the file handle. This is usually written in try...except:

Copy Code code as follows:

f = open ('/tmp/tmp.txt ')
Try
For line in F.readlines ():
Print (line)
Finally
F.close ()

Note that we do not have the IOError to process the file open failed, the above wording works correctly, but for each open file, we have to manually close the file handle. If you want to use with to achieve these functions, you need a proxy class:
Copy Code code as follows:

Class opened (object):

def __init__ (self, name):
Self.handle = open (name)

def __enter__ (self):
Return Self.handle

def __exit__ (self, type, value, Trackback):
Self.handle.close ()

With opened ('/tmp/a.txt ') as F:
For line in F.readlines ():
Print (line)


Notice that we have a helper class named opened and implement the __enter__ and __exit__ methods, the __enter__ method has no parameters, and the 3 parameters of the __exit__ method represent the type of the exception, the value, and the stack information, if there is no exception, The value of 3 parameters is none.

If you don't like defining class, you can also use the contextlib provided by the Python standard library:

Copy Code code as follows:

From Contextlib import ContextManager

@contextmanager
Def opened (name):
f = Open (name)
Try
Yield F
Finally
F.close ()

With opened ('/tmp/a.txt ') as F:
For line in F.readlines ():
Print (line)


Using ContextManager functions, yield can return only one parameter, and yield is followed by code that handles cleanup work. In our example of reading a file, we are closing the file handle. Here the principle and our previous implementation of the class opened is the same, interested can refer to the ContextManager source code.

Third, the application scene

Nonsense so much, so exactly those scenes under the use with, there are some excellent examples? Of course, otherwise the meaning of this article. The following excerpt from PEP 343.

A template that ensures that the code is locked before execution and releases the lock after execution:

Copy Code code as follows:

@contextmanager
def locked (lock):
Lock.acquire ()
Try
Yield
Finally
Lock.release ()

With locked (myLock):
# Code here executes with MyLock held. The lock is
# guaranteed to being released when the ' block was left (even
# if Via return or by a uncaught exception).


Commit and rollback of database transactions:
Copy Code code as follows:

@contextmanager
def transaction (DB):
Db.begin ()
Try
Yield None
Except
Db.rollback ()
Raise
Else
Db.commit ()

REDIRECT stdout:
Copy Code code as follows:

@contextmanager
def stdout_redirected (new_stdout):
Save_stdout = Sys.stdout
Sys.stdout = New_stdout
Try
Yield None
Finally
Sys.stdout = Save_stdout

With opened (filename, "w") as F:
With stdout_redirected (f):
print "Hello World"


Note that the above example is not thread-safe and should be used carefully in a multithreaded environment.


Iv. Summary

With is a simplification of the try...expect...finally syntax and provides a very good way to handle exceptions. There are 2 ways to implement with syntax in Python: The class-based and decorator-based,2 methods are equivalent in principle, and can be chosen according to the specific scenario.

The

With originally originated from a block...as ... Grammar, but this kind of grammar is spurned by many people, finally was born with, regarding this period of history can still refer to PEP-343 and PEP-340

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.