2017-08-09 20 views
1

例如,你如何在一個已經迭代的發電機中捕獲GeneratorExit?

In [33]: def gener(): 
    ...: try: 
    ...:  print('hi') 
    ...:  yield 1 
    ...:  print('hi 2') 
    ...:  yield 2 
    ...: except: 
    ...:  print('Closed: {!r}'.format(sys.exc_info()[1])) 
    ...: 

In [34]: gener().close() 

# ↑ No output! 
In [35]: g = gener() 

In [36]: next(g) 
hi 
Out[36]: 1 

In [37]: g.close() 
Closed: GeneratorExit() 

是沒可能注意到發電機的close()電話,如果你還沒有跨進發生器,在Python?

(在我的實際使用情況,的參數傳遞給發電機一個是返回發電機的功能傳遞給發電機,包括所有權。即資源,

def do_it(): 
    resource = acquire() 
    try: 
     return a_generator(resource)() # pass ownership of the resource 
    except: 
     resource.close() 

如果您在第一次迭代之前關閉發生器,並且發生器無法捕獲該事實,則資源泄漏)。

+0

你可以寫一個基於類發生器和覆蓋close方法。 –

回答

2

您不能。如果發生器不是next ed,則體內任何try子句都沒有輸入。在設置任何異常處理之前,close將在函數的開始處拋出GeneratorExit

你必須改變的處所 - 例如,通過引入虛擬yieldnext提前一旦荷蘭國際集團的發電機:

def gen_wrapper(): 
    gen_iter = _gen() 
    next(gen_iter) 
    return gen_iter 

def _gen(): 
    try: 
     yield 
     ... 
    finally: 
     perform_cleanup() 

# Generator returned from gen_wrapper will perform cleanup even if closed immediately. 
+0

這是我偷偷摸摸的嫌疑。這真是一個恥辱,Python。 – Thanatos

相關問題