2014-01-08 18 views
2

我遇到了Python 2.7的問題,從生成器中引發的異常不可捕獲。生成器中的不可捕捉的異常

我已經失去了相當多的時間,兩次,這種行爲。

def gen_function(): 
    raise Exception("Here.") 

    for i in xrange(10): 
     yield i 

try: 
    gen_function() 
except Exception as e: 
    print("Ex: %s" % (e,)) 
else: 
    print("No exception.") 

輸出:

No exception. 
+2

調用發電機不** **不執行任何代碼。試試'next(gen_function())'。 – Bakuriu

+0

[Python yield關鍵字解釋]可能的重複(http://stackoverflow.com/questions/231767/the-python-yield-keyword-explained) – Bakuriu

+0

@Bakuriu:我覺得這只是回答一些問題而已這個特定的問題,雖然建議完整閱讀 – Claudiu

回答

4

gen_function()會給你發電機對象

你需要調用next()函數調用的代碼。

您可以next功能直接做

for i in g: 
    pass # or whatever you want 

雙方將觸發異常

+1

您可能想調用['next' _function_](http://docs.python.org/2/library/functions.html#next),正如您的文本解釋的那樣,而不是'next' _method_,就像您的示例代碼呢。換句話說,'next(g)'。 (這樣,你的代碼就可以同時適用於2.x和3.x,但更重要的是,它更具慣用性。) – abarnert

2

調用發電機只是給你生成器對象。生成器中沒有代碼實際執行。通常這是不明顯的,因爲你經常應用發生器立即:

for x in gen_function(): 
    print x 

在這種情況下,引發異常。但是哪裏?爲了使它更明確,當發生這種情況我已經作出了明確的for ... in循環(實際上,這就是它背後的幕後):

generator_obj = gen_function() # no exception 
it = iter(generator_obj) # no exception (note iter(generator_obj) is generator_obj) 
while True: 
    try: 
     x = it.next() # exception raised here 
    except StopIteration: 
     break 

    print x 
+0

關於隱藏部分的很好解釋。它涵蓋了絕對的一切(除了3.0-3.3中理解中的不相關的邊緣案例),簡明扼要,以及我認爲新手都能理解的方式。我需要開始保留一個有用的鏈接列表,像這個答案指向未來的問題闡述... – abarnert

+0

@abarnert:很高興你喜歡它!你指的是什麼邊緣情況?我不是很熟悉Python 3 – Claudiu

+1

請看[這裏](http://pastebin.com/7tJ2ArUQ)。通過將循環翻譯爲等效的顯式while/try/break循環,您無法真正解釋3.0-3.3的行爲,因爲'try'中的代碼基本上是語句的一部分。 (請參閱[這裏](http://stupidpythonideas.blogspot.com/2013/06/can-you-optimize-listgenexp.html)以獲取更多詳細信息)。但這很少有用。 – abarnert