2017-10-10 97 views
0

我正在編寫大量使用協程的代碼,並且我希望關閉時的可靠行爲。關於協程的運行代碼close()

說我有一個協同程序和上下文管理器:

from contextlib import contextmanager 

@contextmanager 
def print_context_manager(text): 
    print("Enter", text) 
    yield 
    print("Exit", text) 

def coro(): 
    with print_context_manager("coro"): 
     while True: 
      print("Loop", (yield)) 

我可以用這樣的:

c = coro() 
next(c) 
c.send("Hello ") 
c.send("World!") 
c.close() 

不幸的是,據我所知,沒有辦法執行我自己的代碼c.close()。特別是協程中的上下文管理器從不打印「退出coro」

協程中的上下文管理器的要點是什麼?我是否必須手動想出一種方式來表示流的結束?那麼close()是什麼意思?

見這個例子:https://repl.it/M0XI/0

+1

「尤其是在write_to_file協程文件上下文經理從未關閉文件。「你確定嗎?如果關閉協程並沒有最終運行塊並退出環境管理器,我會感到驚訝。 –

+0

無論是對於生成器協程還是新的類似但不同的異步協程,關閉協程運行'finally'塊和'__exit__'方法。你不需要編寫自己的處理來做到這一點。 – user2357112

+0

下面是演示問題的示例:https://repl.it/M0XI/0。如果你能看到我做錯了什麼,請讓我知道 –

回答

1

你的情況管理器有一個bug。修正它,當協程關閉時它會自動執行清理。

通過在協程暫停時提高GeneratorExit來關閉協程。如果with中的代碼引發異常,則@contextlib.contextmanager會在yield處引發該異常。你的上下文管理器不處理這個問題,所以異常會阻止清理運行。

您需要包裝在一個try-finally的yield,如果你想清理,即使在異常運行做清理工作在finally

@contextmanager 
def print_context_manager(text): 
    print("Enter", text) 
    try: 
     yield 
    finally: 
     print("Exit", text)