捕获生成器内的错误并随后继续

2024-01-20

我有一个应该运行几天的迭代器。我希望捕获并报告错误,然后我希望迭代器继续。或者整个过程可以重新开始。

这是函数:

def get_units(self, scraper):
    units = scraper.get_units()
    i = 0
    while True:
        try:
            unit = units.next()
        except StopIteration:
            if i == 0:
                log.error("Scraper returned 0 units", {'scraper': scraper})
            break
        except:
            traceback.print_exc()
            log.warning("Exception occurred in get_units", extra={'scraper': scraper, 'iteration': i})
        else:
            yield unit
        i += 1

Because scraper可能是代码的许多变体之一,它不可信,我不想处理那里的错误。

但是当错误发生在units.next(),整个事情就停止了。我怀疑是因为迭代器抛出了StopIteration当其中一个迭代失败时。

这是输出(仅最后一行)

[2012-11-29 14:11:12 /home/amcat/amcat/scraping/scraper.py:135 DEBUG] Scraping unit <Element div at 0x4258c710>
[2012-11-29 14:11:13 /home/amcat/amcat/scraping/scraper.py:138 DEBUG] .. yields article
[2012-11-29 14:11:13 /home/amcat/amcat/scraping/scraper.py:138 DEBUG] .. yields article
[2012-11-29 14:11:13 /home/amcat/amcat/scraping/scraper.py:138 DEBUG] .. yields article
[2012-11-29 14:11:13 /home/amcat/amcat/scraping/scraper.py:138 DEBUG] .. yields article
[2012-11-29 14:11:13 /home/amcat/amcat/scraping/scraper.py:138 DEBUG] .. yields article
[2012-11-29 14:11:13 /home/amcat/amcat/scraping/scraper.py:138 DEBUG] .. yields article
[2012-11-29 14:11:13 /home/amcat/amcat/scraping/scraper.py:138 DEBUG] .. yields article
[2012-11-29 14:11:13 /home/amcat/amcat/scraping/scraper.py:138 DEBUG] .. yields article
[2012-11-29 14:11:13 /home/amcat/amcat/scraping/scraper.py:138 DEBUG] .. yields article
[2012-11-29 14:11:13 /home/amcat/amcat/scraping/scraper.py:138 DEBUG] .. yields article
[2012-11-29 14:11:13 /home/amcat/amcat/scraping/scraper.py:138 DEBUG] .. yields article Counter-Strike: Global Offensive Update Released
Traceback (most recent call last):
  File "/home/amcat/amcat/scraping/controller.py", line 101, in get_units
    unit = units.next()
  File "/home/amcat/amcat/scraping/scraper.py", line 114, in get_units
    for unit in self._get_units():
  File "/home/amcat/scraping/games/steamcommunity.py", line 90, in _get_units
    app_doc = self.getdoc(url,urlencode(form))
  File "/home/amcat/amcat/scraping/scraper.py", line 231, in getdoc
    return self.opener.getdoc(url, encoding)
  File "/home/amcat/amcat/scraping/htmltools.py", line 54, in getdoc
    response = self.opener.open(url, encoding)
  File "/usr/lib/python2.7/urllib2.py", line 406, in open
    response = meth(req, response)
  File "/usr/lib/python2.7/urllib2.py", line 519, in http_response
    'http', request, response, code, msg, hdrs)
  File "/usr/lib/python2.7/urllib2.py", line 444, in error
    return self._call_chain(*args)
  File "/usr/lib/python2.7/urllib2.py", line 378, in _call_chain
    result = func(*args)
  File "/usr/lib/python2.7/urllib2.py", line 527, in http_error_default
    raise HTTPError(req.get_full_url(), code, msg, hdrs, fp)
HTTPError: HTTP Error 500: Internal Server Error
[2012-11-29 14:11:14 /home/amcat/amcat/scraping/controller.py:110 WARNING] Exception occurred in get_units

...code ends...

那么如何防止迭代在发生错误时停止呢?

编辑:这是 get_units() 中的代码

def get_units(self):
    """                                                                                                                                                                                                                                  
    Split the scraping job into a number of 'units' that can be processed independently                                                                                                                                                  
    of each other.                                                                                                                                                                                                                       

    @return: a sequence of arbitrary objects to be passed to scrape_unit                                                                                                                                                                 
    """
    self._initialize()
    for unit in self._get_units():
        yield unit

这是一个简化的 _get_units():

INDEX_URL = "http://www.steamcommunity.com"

def _get_units(self):
  doc = self.getdoc(INDEX_URL)  #returns a lxml.etree document

  for a in doc.cssselect("div.discussion a"):
    link = a.get('href')
    yield link

编辑:问题后续:更改函数中的每个 for 循环,以便在每次失败的迭代后自动执行错误处理 https://stackoverflow.com/questions/13648200/alter-for-loops-to-have-continue-and-error-handling-executed-automatically-after


StopIteration是由next()当不再有下一个项目时生成器的方法。它与生成器/迭代器内部的错误无关。

另一件需要注意的事情是,根据迭代器的类型,它可能无法在异常后恢复。如果迭代器是一个带有next方法,一定会起作用。但是,如果它实际上是一个生成器,则不会。

据我所知,这是您的迭代在出现错误后无法继续的唯一原因units.next(). I.e. units.next()失败,下次你调用它时,它无法恢复,它说它是通过抛出一个来完成的StopIteration例外。

基本上你必须向我们展示里面的代码scraper.get_units()让我们理解为什么循环在单次迭代中出现错误后无法继续。如果get_units()是作为生成器函数实现的,很清楚。如果没有,可能是其他原因阻止了它恢复。

UPDATE:解释什么是生成器函数:

class Scraper(object):
    def get_units(self):
        for i in some_stuff:
            bla = do_some_processing()
            bla *= 2  # random stuff
            yield bla

现在,当你打电话时Scraper().get_units(),它不是运行整个函数,而是返回一个生成器对象。呼唤next()就它而言,将执行到第一个yield。等等现在如果内部任何地方发生错误get_units,可以这么说,它会被污染,下次你打电话时next(),它会提高StopIteration,就好像它已经没有给你的东西了。

阅读http://www.dabeaz.com/generators/ http://www.dabeaz.com/generators/ (and http://www.dabeaz.com/coroutines/ http://www.dabeaz.com/coroutines/) 强力推荐。

UPDATE2:一个可能的解决方案https://gist.github.com/4175802 https://gist.github.com/4175802

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

捕获生成器内的错误并随后继续 的相关文章

随机推荐

  • 检测语言的最佳方法是什么? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 是否可以使用循环创建同一组件的多个实例?

    我有一个组件 Component CAU is port CLK in std logic RESET in std logic START in std logic V DIRECTION in vector 3d P ORIGIN in
  • 如何在 ZF2 中创建表单输入/元素

    编辑 我的主要问题现在变成了 如何以某种干净的方式将带有学说实体管理器的 ServiceManager 交到我的表单 元素和输入类手中 继续阅读以查看完整的帖子 我将尝试在这里举例询问 所以请耐心等待 让我知道哪里做错 对了 或者哪里可以改
  • 是否有用于布尔运算的内置“并行”函数?

    我正在寻找类似的功能pmax and pmin但对于布尔运算 例如 parallel and c TRUE TRUE TRUE TRUE c TRUE TRUE TRUE FALSE c TRUE TRUE FALSE TRUE c TRU
  • 在 C++ 中的结构上使用 memset

    我正在努力为我的工作修复旧代码 目前它是用 C 编写的 他们将静态分配转换为动态分配 但没有编辑 memsets memcmp memcpy 这是我的第一次编程实习 所以我的问题就像新手一样 以下代码是用 C 编写的 但我想用 C 编写 我
  • 使用 Python 更新 terraform (.tf) 文件

    我正在尝试使用 python 更新 terraform 模板 尽管我在尝试查找模块时遇到一些问题 例如使用 PyYAML 来更新 yml 文件 我的目标是更新 git 存储库中存在的 terraform 文件 并创建拉取请求 合并时将触发管
  • 如何使用 SDL 2.0.9 创建 Direct3d 11 渲染器

    在我的项目中我必须使用SDL BLENDOPERATION MAXIMUM via SDL ComposeCustomBlendMode 仅在 SDL 2 0 9 中由 direct3d11 渲染器支持 我有 Windows 8 1 和 G
  • array_multisort() 不修改第一个参数中的数组

    我正在尝试排序 ar1按降序排列的值 ar2 什么也没发生 ar1 array arperc ar2 array arid array multisort ar1 ar2 print r ar1 我缺少什么 如果您想使用以下元素 ar2作为
  • 在 R 中同时记录 stdout + stderr 和 stderr

    我想拥有一切stdout stderr在一个日志文件中 同时stderr在另一个 我怎样才能在 R 中实现这一目标 消息必须保留两个日志中所有消息的时间顺序 例如我有以下代码 options warn 1 cat 1st stdout n
  • React Native 中的快速刷新始终完全重新加载应用程序

    这个问题已经在这里被问过好几次了 这是最相关的 https stackoverflow com questions 59424152 fast refresh that was introduced in react native 0 61
  • 通过 CURL 将 Zip 文件下载到文件结构中的实际 Zip 文件

    我正在尝试使用 RubyGem Curb 构建一个文件下载器 看着这个问题 https stackoverflow com questions 5382149 using gem curb curl to download file 我正在
  • Feign 和 HAL/资源

    我有一个通过 spring data rest 公开资源的服务器 据我所知 它使用 HAL 或 HATEOAS 但是当我尝试将它与 Feign 结合使用时 我似乎无法注册一个被拾取的 Jackson2HalModule 我需要做些什么才能将
  • 如何从 Google 地图平台获取天气数据?

    我有一个位置列表 我想知道是否可以从 Google 地图 API 获取天气数据 当我不得不在 Go 中这样做时 我做了这样的事情 package main import bufio context database sql encoding
  • C++11 中默认函数有什么意义?

    C 11 添加了告诉编译器的功能创建默认实现 http en wikipedia org wiki C 2B 2B0x Defaulting 2Fdeleting of standard functions on C 2B 2B objec
  • 如何在 Rails 中向数据库添加多列

    您好 我刚刚在 RoR 中创建了一个数据库 我现在想再添加 10 列 但是 我不想使用一次仅添加 1 列的以下类型的命令 rails generate migration AddClosing Hrs1ToBusinesses closin
  • ASP.NET奇怪的编译错误

    我不知道我的机器出了什么问题 但有一段时间我从 ASP NET 对于我的所有应用程序 收到以下奇怪的错误 Compilation Error Description An error occurred during the compilat
  • 通过匹配两列的值来过滤数据框

    我在 r 中有一个数据框 我想删除两列中字符串值相等的那些行 我在 r 中使用了 match 函数 但无法获得所需的输出 例如我的数据框是 ALDH1A1 ALDH1A1 ITGA7 CHRNA1 PPP1R9A ACTG1 SRGN SR
  • 无法安装漂亮

    我无法 pip install Prettytable 安装它的最佳选择是什么 sudo pip vvv install prettytable Downloading unpacking prettytable Getting page
  • 通过 Intent 发送 Arraylist

    我怎样才能收到定制ArrayList从另一个活动通过Intent 例如 我有这个ArrayList在活动A中 ArrayList
  • 捕获生成器内的错误并随后继续

    我有一个应该运行几天的迭代器 我希望捕获并报告错误 然后我希望迭代器继续 或者整个过程可以重新开始 这是函数 def get units self scraper units scraper get units i 0 while True