【问题标题】:return next(self._sampler_iter) # may raise StopIterationreturn next(self._sampler_iter) # 可能会引发 StopIteration
【发布时间】:2020-11-14 21:43:59
【问题描述】:

出于某种原因,我没有使用enumerate(data loader),而是为数据加载器创建迭代器。在下面显示的while 循环中,它给了我StopIteration 错误。

描述原因的简约代码:

loader = DataLoader(dataset, batch_size=args.batch_size)
dataloader_iter = iter(loader)
while(dataloader_iter):
    X, y = next(dataloader_iter)
    ...

检查迭代器是否为空的正确条件(在 while 循环中指定)是什么?

【问题讨论】:

  • 注意,enumerate 创建了一个迭代器,即一个enumerate 对象。但它当然可以引发 StopIteration,这就是迭代器的工作方式。处理此问题的惯用方法是使用 try-except StopIteration
  • 但是你为什么要这样迭代呢?为什么不for X, y in dataloader_iter
  • 注意,与其他语言不同,Python 中的迭代器协议并没有规定任何方法来检查迭代器是否为空,例如 Java 的 hasNext,相当于 @987654330 的 rasing @ 例外。 Python 通常会依赖于其他类似语言可能提供显式检查方式的异常。请注意,您可以使用next 的第二个参数来提供一些标记值,例如next(iterator, None),但这不是惯用的
  • 我这样迭代的原因是因为我的数据集中有一个损坏的条目(维度不匹配)。所以,每当我在做enumerate(dataloader) 时,它都会抛出一些错误。现在,我在next(dataloader_iter) 周围使用try-catch 来跳过该恶意条目。
  • 啊,解包失败了。好的,使用它是一个足够简单的解决方案。请注意,您可以仍然使用枚举,它只返回一个迭代器(即enumerate 对象是迭代器)

标签: python iterator pytorch


【解决方案1】:

在 Python 中,在很多情况下,将异常用于控制流是标准的。

只需将其包装在 try-except 中:

loader = DataLoader(dataset, batch_size=args.batch_size)
dataloader_iter = iter(loader)
try:
    while True:
        x, y = next(dataloader_iter)
        ...
except StopIteration:
    pass

如果你想在while循环中捕获其他一些错误,你可以将try-except移到里面,但是你必须记住在遇到StopIteration时要跳出循环:

loader = DataLoader(dataset, batch_size=args.batch_size)
dataloader_iter = iter(loader)
while True:
    try:
        x, y = next(dataloader_iter)
        ...
    except SomeOtherException:
        ...
    except StopIteration:
        break

【讨论】:

  • 我可以颠倒trywhile的顺序吗?
  • try-except 可能应该放在 while 循环体中
  • @juanpa.arrivillaga 在某些情况下,您可能需要更多控制并使用while 循环。但是,是的,我同意如果你可以摆脱for 循环,那将是首选。
  • 是的,我误解了 OP,我认为调用 enumerate(loader) 失败了
猜你喜欢
  • 2013-01-03
  • 2016-08-21
  • 2020-01-17
  • 2022-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-19
  • 1970-01-01
相关资源
最近更新 更多