[python] with statement

to sum up

  1. Context Manager provides the Enter () method and The __exit __ () method, with the statement, if specified as a target, would The __enter __ () method returns the value given to this goal.
  2. If an abnormal operation occurs, it will be the type of abnormal values ​​and the track passed to __exit __ () method. If __exit __ () method returns a value of true, then this exception will be suppressed, otherwise the exception will be thrown again.
  3. If an exception occurs, also called __exit __ () method, but passed in parameter is None, None, None. Here usually put code stream file operations such as closed / sessions and the like.

the term

Context Management Protocol (Context Management Protocol) : contains the method the Enter () and Exit (), support

The object of the agreement to implement these two methods

Context Manager (Context Manager) : supports the context management protocol object, this object implements

Enter () and Exit () method. Context Manager runtime context defined execution with the statement to be established,

Responsible for implementing the block with the statement in the context of entry and exit operations. Usually with statements calling context manager,

It can also be used by directly calling its methods

Runtime context (Runtime context) : created by the context manager, the context manager of the Enter () and

Exit () method implementation, Enter () method proceeds runtime context, the bank execution before the statement Exit () in

Seeing the body after the execution context withdraw from running. with statement supports the concept of context is running.

The context expression (Context Expression) : with statement following the keyword with the expression that

To return a context manager object.

Statement body (body-with) : block wrapped with statement, the statement is executed before the tube body would call context

The processor Enter () method, the statement will be executed after completion of execution thereof Exit () method.

The basic syntax

with context_expression [as target(s)]:
    with-body

Here context_expression To return a context manager object that is not assigned to the target as in clause (S), if the clause as specified, then the context manager will Enter () method returns the value assigned to the target (s). target (s) may be a single variable, or by a "()" enclosed tuple (can not be solely by the "," separated list of variables, must be added "()").

Python for some built-in objects improvements, added support for context manager that can be used with statements, such as automatically closing the file automatically get a thread lock and release. Suppose you want to operate on a file, use the with statement can have the following code:

with open(r'somefileName') as somefile:
    for line in somefile:
        print line
        # ...more code

Is used here with the statement, regardless of whether an exception occurs during the processing file, can ensure that after the implementation of the statement has been closed with the open file handles. If conventional try / finally paradigm will be employed similar to the following code:

somefile = open(r'somefileName')
try:
    for line in somefile:
        print line
        # ...more code
finally:
    somefile.close()

By comparison, with statement can reduce the amount of coding. Support has been added for context management protocol as well as module threading, decimal, etc.

Fundamental

Process with statement is executed as follows:

context_manager = context_expression
exit = type(context_manager).__exit__  
value = type(context_manager).__enter__(context_manager)
exc = True   # True 表示正常执行,即便有异常也忽略;False 表示重新抛出异常,需要对异常进行处理
try:
    try:
        target = value  # 如果使用了 as 子句
        with-body     # 执行 with-body
    except:
        # 执行过程中有异常发生
        exc = False
        # 如果 __exit__ 返回 True,则异常被忽略;如果返回 False,则重新抛出异常
        # 由外层代码对异常进行处理
        if not exit(context_manager, *sys.exc_info()):
            raise
finally:
    # 正常退出,或者通过 statement-body 中的 break/continue/return 语句退出
    # 或者忽略异常退出
    if exc:
        exit(context_manager, None, None, None) 
    # 缺省返回 None,None 在布尔上下文中看做是 False
  1. Performing context_expression, generates a context manager context_manager
  2. Call context manager enter () method; If the as clause, then enter the return value () method is assigned to clause as target (s)
  3. Execute the statement body with-body
  4. Regardless of whether the presence of abnormality during the execution context manager Exit () method, Exit () method is responsible for the implementation of "clean" work, such as the release of resources. If no exception occurs during execution, the statement or statements executed bodies break / continue / return, a parameter called places None Exit (None, None, None); if an exception occurs during execution, obtained using sys.exc_info exception information call parameters Exit (exc_type, exc_value, exc_traceback)
  5. When an exception occurs, if the Exit (of the type, value, the traceback calls out) returns False, it will re-thrown, let statement outside with logic to handle exceptions, and this is common practice; if it returns True, then ignore the exception, no longer abnormal processing

Custom Context Manager

Developers can customize the context management protocol support classes. Custom context manager to achieve the desired context management protocol Enter () and Exit () two methods:

  • context_manager .__ enter __ (): enter the context execution context manager, called before the statement executor. statements with the method's return value is assigned to as clause target, if the clause is specified as words
  • context_manager .__ exit __ (exc_type, exc_value , exc_traceback): Exit runtime context associated with a context manager, and returns a Boolean value indicating whether an abnormality occurring process. Parameter indicates the cause abnormal exit the operation, there is no exception occurs when you exit, the three parameters to None. If an exception occurs, the return
    True said they did not handle the exception, otherwise it will re-thrown outside to be processed by the statement with exit code logic in this method. If abnormality occurs inside of the method, it will be substituted by the occurrence of an abnormality in the statement-body statement. To handle exceptions, do not show re-throw an exception that can not be re-thrown by parameters passed in, just to return value to False on it. Then, the context management code detecting whether Exit () failed to handle exceptions

Here a simple example to demonstrate how to build a custom context manager. Note that the context manager must provide the Enter () and exit defined () method, will result in a lack of any AttributeError; with statement will first check whether the exit () method, then check whether defines the Enter () method.

Suppose there is a resource DummyResource, this need to allocate resources before the visit, after their use to relieve; dispensing operation may be put Enter () method, can be placed in a release operation Exit () method. For simplicity, here only to show the current operation by print statements, and no actual resource allocation and release.

class DummyResource:
def __init__(self, tag):
        self.tag = tag
        print 'Resource [%s]' % tag
    def __enter__(self):
        print '[Enter %s]: Allocate resource.' % self.tag
        return self   # 可以返回不同的对象
    def __exit__(self, exc_type, exc_value, exc_tb):
        print '[Exit %s]: Free resource.' % self.tag
        if exc_tb is None:
            print '[Exit %s]: Exited without exception.' % self.tag
        else:
            print '[Exit %s]: Exited with exception raised.' % self.tag
            return False   # 可以省略,缺省的None也是被看做是False

The DummyResource Enter () returns a reference to itself, can be assigned to this reference as a target variable clause; type of the return value may be set according to actual requirements of different types, the context manager does not have to be the object itself.

Exit () method detects exc_tb variables, if not None, showing the occurrence of abnormality, and False represented by the need to deal with exceptions external code logic; Note that if an exception occurs, the default return value None, in boolean context also be considered as False, but since no abnormality occurs, Exit () of the three parameters are None, context management code can detect this situation, do normal processing.

The following access DummyResource with the statement:

with DummyResource('Normal'):
    print '[with-body] Run without exceptions.'
 
with DummyResource('With-Exception'):
    print '[with-body] Run with exception.'
    raise Exception
    print '[with-body] Run with exception. Failed to finish statement-body!'

The results of the first one with the following statement:

Resource [Normal]
[Enter Normal]: Allocate resource.
[with-body] Run without exceptions.
[Exit Normal]: Free resource.
[Exit Normal]: Exited without exception.

It can be seen complete body will first execute the statement with-body during normal execution, and then executed Exit () method to release resources.

The results of the first two with the following statement:

Resource [With-Exception]
[Enter With-Exception]: Allocate resource.
[with-body] Run with exception.
[Exit With-Exception]: Free resource.
[Exit With-Exception]: Exited with exception raised.
 
Traceback (most recent call last):
  File "G:/demo", line 20, in <module>
   raise Exception
Exception

You can see, with-body is not executing the exception occurs with-body but will ensure that resources are freed, while anomalies generated by other than statements with the code logic to capture processing

Guess you like

Origin www.cnblogs.com/cjwnb/p/11627417.html