Python 生成器中的不可调度异常

Python 生成器中的不可调度异常,python,exception,generator,yield,Python,Exception,Generator,Yield,我在Python2.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."

我在Python2.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.
gen\u function()
将为您提供生成器对象

您需要调用
next()
函数来调用代码

您可以使用
next
功能直接执行此操作

g = gen_function()
next(g)


这两种方法都会触发一个异常

调用生成器只会给您提供生成器对象。生成器中没有实际执行的代码。通常这并不明显,因为您通常会立即应用生成器:

for x in gen_function():
    print x
在这种情况下,将引发异常。但是在哪里呢?为了在发生这种情况时使其更加明确,我已经为。。。在循环中(这基本上就是它在幕后所做的):


调用生成器不会执行任何代码。尝试
next(gen_function())
。可能重复@Bakuriu:我觉得仅仅为了回答这个特定的问题,需要做的事情有点多,尽管建议您通读一遍。编辑也值得阅读教程部分和发电机的下一部分,其中涵盖了大部分内容(或者至少比你自己试着用试错法弄明白的要好)。谢谢所有的答案。我是个白痴,我通常会在另一个上下文中遇到这种与生成器相关的问题,所以我没有意识到。正如本文所解释的,您可能希望调用
next
方法,而不是像示例代码那样调用
next(g)
。(这样,您的代码可以同时使用2.x和3.x,但更重要的是,它更惯用。)对“隐藏”部分的精彩解释。它涵盖了所有内容(除了3.0-3.3中理解中不相关的边缘案例),简明扼要,而且我认为新手可以理解。我需要开始保留一个类似于此答案的有用链接列表,以便在以后的问题中详细说明…@abarnert:很高兴你喜欢它!你指的是什么边缘案例?我对Python 3See不太熟悉。你无法通过tra真正解释3.0-3.3的行为将循环转换为等效的显式while/try/break循环,因为
try
中的代码基本上是语句的一部分。(请参阅以了解更多详细信息。)但这很少相关。
for x in gen_function():
    print x
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