1

我是使用异常处理的新手。我正在使用 mechanize 模块来抓取几个网站。我的程序经常失败,因为连接速度慢并且请求超时。我希望能够在每次尝试之间延迟 30 秒后重试网站(例如超时)最多 5 次。

我查看了这个stackoverflow 答案,可以看到如何处理各种异常。我也看到(虽然它看起来很笨拙)我如何将尝试/异常放在一个while循环中来控制5次尝试......但我不明白如何跳出循环,或者在连接时“继续”成功并且没有抛出异常。

from mechanize import Browser
import time

b = Browser()
tried=0
while tried < 5:
  try:
    r=b.open('http://www.google.com/foobar')
  except (mechanize.HTTPError,mechanize.URLError) as e:
    if isinstance(e,mechanize.HTTPError):
      print e.code
      tried += 1
      sleep(30)
      if tried > 4:
        exit()
    else:
      print e.reason.args
      tried += 1
      sleep(30)
      if tried > 4:
        exit()

print "How can I get to here after the first successful b.open() attempt????"

我将不胜感激有关(1)如何在成功打开时跳出循环,以及(2)如何使整个块不那么笨拙/更优雅的建议。

4

3 回答 3

4

您的第一个问题可以通过以下方式完成break

while tried < 5:
  try:
    r=b.open('http://www.google.com/foobar')
    break
  except #etc...

然而,真正的问题是你真的想要:这就是所谓的“意大利面条代码”:如果你试图通过程序绘制执行图,它看起来就像一盘意大利面条。

您遇到的真正(恕我直言)问题是您退出 while 循环的逻辑有缺陷。与其在多次尝试后尝试停止(这种情况永远不会发生,因为您已经退出了),而是循环直到您获得连接:

#imports etc

tried=0
connected = False
while not Connected:
    try:
        r = b.open('http://www.google.com/foobar')
        connected = true # if line above fails, this is never executed
    except mechanize.HTTPError as e:
        print e.code            
        tried += 1        
        if tried > 4:
            exit() 
        sleep(30)

    except mechanize.URLError as e:
        print e.reason.args            
        tried += 1
        if tried > 4:
            exit()        
        sleep(30)

 #Do stuff
于 2013-03-25T11:42:04.470 回答
2

在任何一种情况下,您都不必在 except 块中重复操作。

from mechanize import Browser
import time

b = Browser()
tried=0
while True:
  try:
    r=b.open('http://www.google.com/foobar')
  except (mechanize.HTTPError,mechanize.URLError) as e:
      tried += 1
    if isinstance(e,mechanize.HTTPError):
      print e.code
    else:
      print e.reason.args
    if tried > 4:
      exit()
    sleep(30)
    continue
  break

此外,您可以while not r:根据Browser.open返回的内容使用。

编辑:roadierich展示了一种更优雅的方式

try:
  doSomething()
  break
except:
  ...

因为错误会跳到 except 块。

于 2013-03-25T11:32:40.157 回答
1

对于您的第一个问题,您只需要打破循环的“break”关键字。

对于第二个问题,一个“尝试”可以有多个“除外”子句,用于不同类型的异常。这取代了您的 isinstance() 检查,并使您的代码更清晰。

于 2013-03-25T11:28:14.983 回答