For details about the use of the with keyword in Python, for details about the use of python

Source: Internet
Author: User

For details about the use of the with keyword in Python, for details about the use of python

In Python 2.5, The with keyword is added. It makes the common try... try t... finally... mode easy to reuse. Let's look at a classic example:

with open('file.txt') as f:  content = f.read()

In this Code, no matter what happens to the code block in with during execution, the file will eventually be closed. If a code block has an exception during execution, the program closes the opened file before the exception is thrown.

Let's look at another example.

When initiating a database transaction request, code similar to this is often used:

db.begin()try:  # do some actionsexcept:  db.rollback()  raisefinally:  db.commit()

If you change the operation that initiates a transaction request to support the with keyword, you can use code like this:

with transaction(db):  # do some actions

The following describes in detail the with execution process and implements the above Code in two common ways.

General with Execution Process

The structure of a basic with expression is as follows:

with EXPR as VAR:  BLOCK

EXPR can be any expression, and as VAR is optional. The general execution process is as follows:

  1. Calculate EXPR and obtain a context manager.
  2. The _ exit () _ method of the context manager is saved for subsequent calls.
  3. Call the _ enter () _ method of the context manager.
  4. If the with expression contains as VAR, the return value of EXPR is assigned to VAR.
  5. Execute the expression in the BLOCK.
  6. Call the _ exit () _ method of the context manager. If an exception occurs during BLOCK execution and causes the program to exit, the type, value, and traceback (sys. the return value of exc_info () is passed as a parameter to the _ exit () _ method. Otherwise, three None are passed.

The process is represented in Code as follows:

Mgr = (EXPR) exit = type (mgr ). _ exit _ # value = type (mgr) is not executed here ). _ enter _ (mgr) exc = Truetry: try: VAR = value # if as var block does T: exc = False if not exit (mgr, * sys. exc_info (): raisefinally: if exc: exit (mgr, None)

This process has several details:

If no _ enter () _ or _ exit () _ method exists in the context manager, the interpreter throws an AttributeError.
If the _ exit () _ method returns a value that can be regarded as True after an exception occurs in the BLOCK, the exception will not be thrown, the subsequent code will continue to be executed.

Next, use two methods to implement the above process.

Implement the context manager class

The first method is to implement a class, which contains an instance attribute db and the methods required by the context manager _ enter () _ and _ exit ()__.

class transaction(object):  def __init__(self, db):    self.db = db  def __enter__(self):    self.db.begin()  def __exit__(self, type, value, traceback):    if type is None:      db.commit()    else:      db.rollback()

After understanding the with execution process, this implementation method is easy to understand. The implementation method described below is much more complicated to understand.

Use the generator decorator

In the Python standard library, there is a modifier that can get the context Manager through the generator. The implementation process of using the generator decorator is as follows:

from contextlib import contextmanager@contextmanagerdef transaction(db):  db.begin()  try:    yield db  except:    db.rollback()    raise  else:    db.commit()

At first glance, this implementation method is simpler, but its mechanism is more complex. Let's take a look at the execution process:

  1. After the Python interpreter recognizes the yield keyword, def will create a generator function to replace the regular function (I like to replace the method with the function in addition to the class definition ).
  2. Contextmanager is called and a help method is returned. After the contextmanager is called, a GeneratorContextManager instance is generated. In the end, expr in the with expression calls the help function returned by the contentmanager modifier.
  3. The with expression calls transaction (db), which is actually a help function. The help function calls the generator function. The generator function creates a generator.
  4. The help function passes the generator to GeneratorContextManager and creates an instance object of GeneratorContextManager as the context manager.
  5. The with expression calls the _ enter () _ method of the context manager of the Instance Object.
  6. The next () method of the generator is called in the _ enter () _ method. At this time, the generator method will stop at the yield db and use the db as the return value of next. If there is as VAR, it will be assigned to VAR.
  7. The BLOCK in with is executed.
  8. After the BLOCK is executed, call the _ exit () _ method of the context manager. The _ exit () _ method calls the next () method of the generator again. If a StopIteration exception occurs, pass.
  9. If no exception occurs in the generator method, db. commit () is executed; otherwise, db. rollback () is executed ().

Let's take a look at the code implementation of the above process again:

def contextmanager(func):  def helper(*args, **kwargs):    return GeneratorContextManager(func(*args, **kwargs))  return helperclass GeneratorContextManager(object):  def __init__(self, gen):    self.gen = gen  def __enter__(self):    try:      return self.gen.next()    except StopIteration:      raise RuntimeError("generator didn't yield")  def __exit__(self, type, value, traceback):    if type is None:      try:        self.gen.next()      except StopIteration:        pass      else:        raise RuntimeError("generator didn't stop")    else:      try:        self.gen.throw(type, value, traceback)        raise RuntimeError("generator didn't stop after throw()")      except StopIteration:        return True      except:        if sys.exc_info()[1] is not value:          raise

Summary

The with expression in Python contains many Python features. Taking a moment to get familiar with is very worthwhile.

Some other examples

Lock Mechanism

@contextmanagerdef locked(lock):  lock.acquired()  try:    yield  finally:    lock.release()

Standard output redirection

@contextmanagerdef stdout_redirect(new_stdout):  old_stdout = sys.stdout  sys.stdout = new_stdout  try:    yield  finally:    sys.stdout = old_stdoutwith open("file.txt", "w") as f:  with stdout_redirect(f):    print "hello world"

References

The Python "with" Statement by Example

PEP 343

Related Article

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.