Using the WITH keyword in python

Source: Internet
Author: User
This article focuses on Python with the use of the keyword with the relevant information, in Python, with the keyword is a management for you to implement the context protocol object of good things, the need for friends can refer to the next

">

In Python 2.5, the WITH keyword is added. It will be commonly used in try ... except ... finally ... The mode is easily reused. Look at one of the most classic examples:

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

In this code, the file will eventually be closed, regardless of the code block in the with, whatever happens during execution. If an exception occurs during the execution of the code block, the program closes the open file before the exception is thrown.

Let's look at another example.

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

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

If the operation initiating the transaction request becomes capable of supporting the WITH keyword, then code like this is available:

With transaction (db):  # do some actions

The following is a detailed explanation of the execution of the with and the implementation of the above code in two common ways.

General execution process with

A basic with expression, which is structured like this:

With EXPR as VAR:  BLOCK

Where: EXPR can be an arbitrary expression, as VAR is optional. Its general implementation process is this:

    1. Evaluates EXPR, and gets a context manager.

    2. The exit () method of the context manager is saved for subsequent calls.

    3. Invokes the context Manager's enter () method.

    4. If the with expression contains as Var, then the return value of EXPR is assigned to Var.

    5. Executes an expression in the BLOCK.

    6. Invokes the exit () method of the context manager. If an exception occurs during BLOCK execution that causes the program to exit, the exception type, value, and Traceback (the return value of Sys.exc_info () are passed as parameters to the exit () method. Otherwise, three None will be passed.

This process is represented in code, like this:

MGR = (EXPR) exit = Type (MGR). Exit # There is no execution value = Type (MGR). Enter (mgr) exc = Truetry:  try:    var = value # If you have as VAR    BLOCK  except:    exc = False    if not exit (Mgr, *sys.exc_info ()):      raisefinally:  if exc:    exit (Mgr, none, none, none)

This process has several details:

If there is no method in the context manager for enter () or exit (), then the interpreter throws a attributeerror.
After an exception occurs in the BLOCK, if the exit () method returns a value that can be treated as True, the exception is not thrown and the subsequent code continues to execute.

Next, implement the above procedure in two ways.

Implementing the Context Manager class

The first approach is to implement a class that contains an instance of the property db and the method 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 ()

Once you understand the execution of the with, this implementation is easy to understand. The implementation is described below, and its principles are much more complex to understand.

Using the builder Adorner

In Python's standard library, there is an adorner that gets the context manager through the builder. The implementation process for using the builder adorner 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 is simpler, but its mechanism is more complex. Take a look at the process:

  1. After the Python interpreter recognizes the yield keyword, Def creates a generator function instead of a regular function (outside of the class definition I prefer to use a function instead of a method).

  2. The adorner ContextManager is called and returns a helper method that generates a Generatorcontextmanager instance after it is called. The final call to EXPR in the with expression is the helper function returned by the Contentmanager adorner.

  3. The WITH expression calls transaction (db), which is actually called the help function. The helper function calls the generator function, which creates a generator function.

  4. The Help function passes this generator to Generatorcontextmanager and creates an Generatorcontextmanager instance object as the context manager.

  5. The WITH expression invokes the Enter () method of the context manager of the instance object.

  6. The next () method of this generator is called in the Enter () method. At this point, the generator method executes to stop at yield DB and takes the DB as the return value of next (). If there is as Var, then it will be assigned to Var.

  7. The BLOCK in with is executed.

  8. The exit () method of the context manager is called after the BLOCK execution finishes. The exit () method calls the next () method of the generator again. Pass if a stopiteration exception occurs.

  9. If the exception generator method does not occur, Db.commit () will be executed, otherwise db.rollback () will be executed.

Take a look at the code for the above procedure in general:

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

Summarize

Python's with expression contains a lot of Python features. Taking the time to thoroughly understand with is a very worthwhile thing.

A few 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"

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.