【问题标题】:Uncatchable Exceptions in Generators生成器中无法捕获的异常
【发布时间】:2014-01-27 02:46:00
【问题描述】:

我在使用 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.

【问题讨论】:

  • 调用生成器不会执行任何代码。请改用next(gen_function())
  • @Bakuriu:我觉得要回答这个特定的问题有点费劲,不过建议通读一遍
  • 还值得阅读Iterators 上的教程部分和生成器的以下部分,它们很好地涵盖了大部分内容(或者至少比你试图弄清楚它所得到的要好)自己通过反复试验)。
  • 感谢您的所有回答。我这个白痴,我通常在另一个上下文中遇到这种与生成器相关的问题,所以我没有认识到它。

标签: python exception generator yield


【解决方案1】:

gen_function() 会给你生成器object

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

你可以直接用next函数来做

g = gen_function()
next(g)

for i in g:
    pass # or whatever you want

两者都会触发异常

【讨论】:

  • 您可能想要调用next function,正如您的文本所解释的那样,而不是像您的示例代码那样调用next 方法。换句话说,next(g)。 (这样,您的代码可以同时使用 2.x 和 3.x,但更重要的是,它更加地道。)
【解决方案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

【讨论】:

  • 对幕后部分的精彩解释。它绝对涵盖了所有内容(除了 3.0-3.3 中的理解中不相关的边缘情况),简明扼要,并且以我认为新手可以理解的方式。我需要开始保留一个有用的链接列表,比如这个答案,以便在以后的问题中详细说明……
  • @abarnert:很高兴你喜欢它!你指的边缘情况是什么?我对 Python 3 不是很熟悉
  • here。您无法通过将循环转换为等效的显式 while/try/break 循环来真正解释 3.0-3.3 的行为,因为 try 中的代码基本上是语句的一部分。 (请参阅 here 了解比您想要的更多详细信息。)但这很少有相关性。
猜你喜欢
  • 1970-01-01
  • 2019-10-19
  • 2016-06-16
  • 2010-10-29
  • 1970-01-01
  • 2011-04-19
  • 1970-01-01
  • 2021-10-09
相关资源
最近更新 更多