Python context Manager

Source: Internet
Author: User

Context Manager

In Python programming, you can often encounter this situation: there is a special block of statements that need to perform some preparatory actions before executing this block of statements, and after the statement block execution completes, you need to continue to perform some finishing actions.

For example, when you need to manipulate a file or database, you first need to get a file handle or database connection object, when you have done the appropriate operation, you need to release the file handle or close the database connection action.

As another example, when a multithreaded program needs access to critical resources, the thread first needs to acquire the mutex, and when execution is complete and ready to exit the critical section, the mutex needs to be released.

For these cases, the context Manager concept is provided in Python, and the context manager can be used to define/control the pre-action of the code block before execution and the closing action after execution.

Context Management Protocol

So how do you implement a context manager in Python? Here, there are also two "magic methods", __enter__ and __exit__, the following is a detailed description of these two methods.

    • __enter__ (self) defines what the context manager should does at the beginning of the block created by the with STA Tement. Note that the return value of __enter__ was bound to the target of the WITH statement, or the name after the AS.
    • __exit__ (self, exception_type, Exception_value, Traceback) defines what the context manager should does after its block has been executed (or terminates). It can be used to handle exceptions, perform cleanup, or does something always doing immediately after the action in the bloc K. IF The block executes successfully, Exception_type, Exception_value, and Traceback would be None. Otherwise, can choose to handle the exception or let the user handle it; If you want to handle it, make sure __exit__ returns True after all are said and done. If you don ' t want the exception-to is handled by the context manager, just let it happen.

That is, when we need to create a context manager type, we need to implement the __enter__ and __exit__ methods, which is called the context manager Protocol. Defines a run-time context environment.

With statement

In Python, the context manager can be conveniently used with the WITH statement, which can enter a run-time context (executing the __enter__ method) before the code block runs, and exit the context after the code block finishes (the __exit__ method is executed).

The syntax for the WITH statement is as follows:

With context_expr [as Var]:    with_suite
    • CONTEXT_EXPR is an object that supports the context management protocol, which is the context Manager object that is responsible for maintaining the context
    • As Var is an optional part that saves context manager objects by variable means
    • With_suite is a block of statements that need to be executed in the context

In Python's built-in types, there are many types that support context-management protocols, such as File,thread. Locktype,threading. Lock and so on. Here we take the file type as an example to see the use of the WITH statement.

With statement simplifies file operations

When you need to write a file, it will generally be done in the following way. The try-finally statement block is used in the code to ensure that the file handle is closed even if an exception occurs.

Logger = open ("log.txt""w")try:    Logger.write (')    logger.write (' World  ')finally:    logger.close ()print logger.closed    

In fact, Python's built-in file type supports the context management protocol, and can be viewed directly through the built-in function dir () to see the methods and properties supported by file:

>>>Printdir (file) ['__class__','__delattr__','__doc__','__enter__','__exit__','__format__','__getattribute__', '__hash__', '__init__', '__iter__', '__new__', '__reduce__','__reduce_ex__','__repr__','__setattr__','__sizeof__','__str__','__subclasshook__', 'Close', 'Closed', 'Encoding', 'Errors', 'Fileno', 'Flush', 'Isatty', 'Mode', 'Name', 'Newlines', 'Next', 'Read', 'Readinto', 'ReadLine', 'ReadLines','Seek','Softspace',' Tell','truncate','Write','Writelines','Xreadlines']>>>

As a result, the code above can be simplified with the WITH statement, but the code is the same, but using the WITH statement is more concise:

With open ("log.txt""w") as logger:    logger.write (       logger.write (' World ') )    print logger.closed    
Custom Context Manager

For custom types, the context Manager can be implemented by implementing the __ENTER__ and __exit__ methods.

Looking at the following code, a MyTimer type is defined in the code that implements the timing function of the code block:

Import TimeclassMyTimer (object):def __init__(Self, verbose =False): Self.verbose=verbosedef __enter__(self): Self.start=time.time ()return Selfdef __exit__(Self, *unused): Self.end=time.time () self.secs= Self.end-Self.start self.msecs= self.secs * 1000ifSelf.verbose:Print "Elapsed Time:%f Ms"%self.msecs

This context manager is used in conjunction with the WITH statement:

def fib (n):     if inch [1, 2]:         return 1    else:        return fib (n-1) + fib (n-2) with        MyTimer ( True):    Print fib (30)

The result of the code output is:

Exception Handling and __exit__

In the context Manager, if the code block (with_suite) produces an exception, the __exit__ method is called, and the __exit__ method has different exception handling methods.

When the __exit__ method exits the current run-time context, a Boolean value is returned that indicates whether the exception needs to be ignored if the code block (with_suite) is executing.

1. __exit__ return False, re-throw (re-raised) exception to upper level

Modify the previous example by adding a parameter "ignoreexception" to the MyTimer type to indicate whether the context manager ignores the exception that is generated in the code block (with_suite).

Import TimeclassMyTimer (object):def __init__(self, verbose = False, ignoreexception =False): Self.verbose=verbose self.ignoreexception=ignoreexceptiondef __enter__(self): Self.start=time.time ()return Selfdef __exit__(Self, *unused): Self.end=time.time () self.secs= Self.end-Self.start self.msecs= self.secs * 1000ifSelf.verbose:Print "Elapsed Time:%f Ms"%Self.msecsreturnself.ignoreexceptionTry: With MyTimer (True, False):RaiseException ("ex4test")exceptException, E:Print "Exception (%s) was caught"%eElse:Print "No Exception happened"

Running this code results in the following result, because the __exit__ method returns false, so the exception in the code block (With_suite) will continue to be thrown into the upper code.

2. __exit__ returns ture, exception in code block (with_suite) is ignored

To change the code to __EXIT__ returns true:

Try :            with MyTimer (True, True):        raise Exception ("ex4test")  except  Exception, E:    print"Exception (%s) was caught " %eelse:    print"No Exception happened "

The result becomes the following, the exception in the code block (with_suite) is ignored, and the code continues to run:

Be careful to use __exit__ to return to ture unless it is clear why.

3. Get more exception information through the full signature of the __EXIT__ function

For the __exit__ function, its full signature is as follows, meaning more information about the exception can be obtained by this function.

    • __exit__ (self, exception_type, Exception_value, Traceback)

Continue to modify the __exit__ function in the above example as follows:

def __exit__(self, exception_type, Exception_value, traceback): Self.end=time.time () self.secs= Self.end-Self.start self.msecs= self.secs * 1000ifSelf.verbose:Print "Elapsed Time:%f Ms"%Self.msecsPrint "Exception_type:", Exception_typePrint "Exception_value:", Exception_valuePrint "Traceback:", TracebackreturnSelf.ignoreexception

In this running result, more information about the exception is shown:

Summarize

This article describes the context manager in Python and how to use the context Manager in conjunction with the WITH statement.

Summarize the execution flow of the WITH statement:

    • Executes context_expr to get the context Manager object
    • Invoke the __enter__ () method of the context manager
      • If there is an as VAR clause, assign the return value of the __enter__ () method to Var
    • Execute code block With_suite
    • Invokes the __exit__ () method of the context manager, and if With_suite produces an exception, the type, value, and traceback of the exception are passed as arguments to __exit__ (), otherwise three None is passed
      • If With_suite produces an exception, and the return value of __exit__ () is equal to False, then the exception will be re-thrown to the upper
      • If With_suite produces an exception, the return value of the weapon __exit__ () is equal to True, then the exception is ignored and the subsequent code is executed.

In many cases, the WITH statement can simplify the code and increase the robustness of the code.

Python context manager

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.