1. 程式人生 > >python關於__ enter__和__exit__方法,with語句

python關於__ enter__和__exit__方法,with語句

1.上下文管理協議

A context manager is an object that defines the runtime context to be established when executing a with statement. The context manager handles the entry into, and the exit from, the desired runtime context for the execution of the block of code. Context managers are normally invoked using the with statement (described in section The with statement), but can also be used by directly invoking their methods.
Typical uses of context managers include saving and restoring various kinds of global state, locking and unlocking resources, closing opened files, etc.
上下文管理器是一個物件,它定義在執行with語句時要建立的執行時上下文。 上下文管理器處理進入和退出所需執行時上下文以執行程式碼塊。 通常使用with語句呼叫上下文管理器(在with語句一節中描述),但也可以通過直接呼叫它們的方法來使用。
上下文管理器的典型用途包括儲存和恢復各種全域性狀態,鎖定和解鎖資源,關閉開啟的檔案等。

上下文管理器是用來定義執行with語句時建立的執行時上下文的一個物件,通過呼叫物件的__ enter__和__ exit__ 方法來實現

2.__ enter__()

object.__ enter__(self)
Enter the runtime context related to this object. The with statement will bind this method’s return value to the target(s) specified in the as clause of the statement, if any.
進入物件的執行時上下文,with語句會把這個方法的返回值賦給as指定的變數.

3.__ exit__

object.__ exit__(self, exc_type, exc_value, traceback)
Exit the runtime context related to this object. The parameters describe the exception that caused the context to be exited. If the context was exited without an exception, all three arguments will be None.
If an exception is supplied, and the method wishes to suppress the exception (i.e., prevent it from being propagated), it should return a true value. Otherwise, the exception will be processed normally upon exit from this method.
Note that __ exit__() methods should not reraise the passed-in exception; this is the caller’s responsibility.

退出物件的執行時上下文,引數描述了導致上下文退出的異常資訊.當正常退出時,三個引數都為None, 如果異常發生,則引數記錄異常資訊:exc_type(異常型別), exc_value(異常資訊), traceback(異常追蹤).
如果希望exit阻止異常報出, 那應該返回True(返回True則正常執行with後面的語句). 否則exit執行結束後會正常丟擲異常資訊.
注意,exit方法不應該重新丟擲被傳入的異常, 這是呼叫者的責任(?)

使用示例:

class Context:
    def __init__(self, name):
        self.name = name

    def __enter__(self):
        print('enter running')
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('exit running')
        print(exit, exc_type, exc_val, exc_tb, sep='\n')

with Context('sabi') as t:
    print(t.name)
    print(t.__dict__)

print('hhahahah')

#result
enter running
sabi
{'name': 'sabi'}
exit running
Use exit() or Ctrl-Z plus Return to exit
None
None
None
hhahahah

4.with語句

The with statement is used to wrap the execution of a block with methods defined by a context manager (see section With Statement Context Managers). This allows common try…except…finally usage patterns to be encapsulated for convenient reuse.

with語句利用上下文管理器來包裝要執行的語句塊, 這樣可以將try,except等使用模式封裝起來以便重用.

with語句執行流程:

The execution of the with statement with one “item” proceeds as follows:
1.The context expression (the expression given in the with_item) is evaluated to obtain a context manager.
評估上下文表達式以獲得上下文管理器

2.The context manager’s __ exit__() is loaded for later use.

3.The context manager’s __ enter__() method is invoked.

4.If a target was included in the with statement, the return value from __ enter__() is assigned to it.
Note:
The with statement guarantees that if the __ enter__() method returns without an error, then __ exit__() will always be called. Thus, if an error occurs during the assignment to the target list, it will be treated the same as an error occurring within the suite would be. See step 6 below.
注意:enter的返回結果賦值給with指定的變數時出錯, 則視為在執行with下的語句塊時出錯,exit依然會觸發.

5.The suite is executed.

6.The context manager’s __ exit__() method is invoked. If an exception caused the suite to be exited, its type, value, and traceback are passed as arguments to __ exit__(). Otherwise, three None arguments are supplied.
If the suite was exited due to an exception, and the return value from the __ exit__() method was false, the exception is reraised. If the return value was true, the exception is suppressed, and execution continues with the statement following the with statement.
If the suite was exited for any reason other than an exception, the return value from __ exit__() is ignored, and execution proceeds at the normal location for the kind of exit that was taken.

4.2多個with疊加
With more than one item, the context managers are processed as if multiple with statements were nested:

with A() as a, B() as b:
    suite

# is equivalent to

with A() as a:
    with B() as b:
        suite