【问题标题】:Combining 'while not' with try/except将 'while not' 与 try/except 结合
【发布时间】:2016-01-20 23:31:56
【问题描述】:

我得到一个带有urllib2 的页面,然后用lxml 解析它。通常有两件事会出错:urllib2.URLError,或httplib.IncompleteRead

def get_page(url):
    response = None
    while not response:
        try:
            response = urllib2.urlopen(url)
        except urllib2.URLError:
            response = urllib2.urlopen(url)
        except httplib.IncompleteRead:
            print '**** IncompleteRead for response from %s, retrying' % url
        html_parser = etree.HTMLParser()
        tree = etree.parse(response, html_parser)
        return tree

这里有几个明显的问题:

  1. 第一个 except 与前面的 try 执行完全相同的操作。
  2. 无论我们是否有response,都将尝试使用lxml 进行解析。

所以:

  1. 第一个except 需要做什么? pass 可以接受吗?
  2. 我的理解是,在try 中只能尝试一个操作,所以我不愿意将解析移到那里。事实上,一个函数本身应该只执行一个动作——解析是否属于它自己的函数?

【问题讨论】:

  • 如果你想在这两种情况下都重试,你可以except (urllib2.URLError, httplib.IncompleteRead):用相同的代码处理这两种异常。
  • “这里有几个明显的问题”——这些问题对我们来说并不明显,因为您实际上还没有描述代码应该做什么。例如如果提出URLError 会发生什么?如果提出IncompleteRead 会发生什么?

标签: python python-2.7 while-loop try-catch


【解决方案1】:

您可以使用continuebreak 语句的组合来处理这些情况。 continue会跳回while循环的顶部,break会跳出while循环。

def get_page(url):
    response = None
    while not response:
        try:
            response = urllib2.urlopen(url)
        except urllib2.URLError:
            continue  # No response, try again
        except httplib.IncompleteRead:
            print '**** IncompleteRead for response from %s, retrying' % url
            break  # Bad response, don't try again?
        html_parser = etree.HTMLParser()
        tree = etree.parse(response, html_parser)
        return tree

您还可以在此处混合使用其他流控制工具(例如 tryelse 子句,仅当块中发生异常时才会执行):

try:
    pass
except Exception as err:
    print("Don't see this.")
else:
    print("You will see this.")

相对于:

try:
    raise Exception
except Exception as err:
    print("You will see this.")
else:
    print("Don't see this.")

【讨论】:

    【解决方案2】:

    我认为您想将解析移出while 循环,而不是移入try 块。这样,您可以继续循环尝试获取有效响应,并且仅在请求成功时才尝试解析。

    def get_page(url):
        response = None
        while not response:
            try:
                response = urllib2.urlopen(url)
            except urllib2.URLError:
                print '**** URLError for response from %s, retrying' % url
            except httplib.IncompleteRead:
                print '**** IncompleteRead for response from %s, retrying' % url
    
        html_parser = etree.HTMLParser()
        tree = etree.parse(response, html_parser)
        return tree
    

    我还更新了URLErrorexcept 块,使其与IncompeleteRead 块的工作原理基本相同。我实际上不确定这是否合适,因为某些URLErrors 可能无法通过重试来修复(例如,如果服务器不存在,那么在您重试时可能不会改变)。如果它应该是一个致命错误(至少对这个函数来说是致命的),你可能想要在那个 except 块中 raise,而不是让循环继续。这是一个比IncompleteReads 更重视URLErrors 的版本:

    def get_page(url):
        response = None
        while not response:
            try:
                response = urllib2.urlopen(url)
            except urllib2.URLError:
                print '**** URLError for response from %s, giving up' % url
                raise
            except httplib.IncompleteRead:
                print '**** IncompleteRead for response from %s, retrying' % url
    
        html_parser = etree.HTMLParser()
        tree = etree.parse(response, html_parser)
        return tree
    

    raise 关键字本身(后面没有表达式)重新引发当前异常。如果这对您的应用程序更有意义,您还可以引发不同的错误(例如,ValueError,表示提供的 URL 不好)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-14
      • 2019-09-28
      • 1970-01-01
      • 2015-11-22
      • 2018-11-06
      • 2021-12-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多