Python脚本循环挂起

时间:2011-03-29 20:44:25

标签: python loops freeze

在我的一个脚本中,我使用以下无限循环来检查有效的互联网连接:

def online_check():
    try:
        con = urllib2.urlopen("http://www.google.com/")
        data = con.read()
        logging.debug('{0} Reached the host. Exiting online_check'.format(time.strftime('[ %H:%M:%S ]')))
    except:
        logging.debug('{0} Could not reach host trying again in 3 seconds'.format(time.strftime('[ %H:%M:%S ]')))
        time.sleep(3)
        online_check()

我知道这不是一个非常优雅的解决方案,但问题是,当我启动我的脚本时,它有时会调用online_check方法并卡在其中间(一次大约200次尝试)。该脚本仍在运行,不会抛出任何异常;脚本卡住了。我可以按CTRL + C(即使脚本被卡住了几个小时),它只会抛出异常并继续下一个online_check。我还重写了脚本来检查'ifconfig'中的IP地址,而不是ping谷歌,不幸的是有类似的结果。

我做错了什么?我可以重写脚本,这样就不会发生吗?有什么我可以做的来找出这里发生了什么?

非常感谢帮助。顺便说一句。我正在使用Python2.7.1,我在Linux和Mac上都尝试过这个脚本。

P.S:如果您有设计方法来检查连接而不使用带宽和最小开销,我会非常乐意听到它。

4 个答案:

答案 0 :(得分:4)

你正在进行无限递归,你可以做的一个方法就是将一个参数传递给online_check进行最大限度的检查。

如:

def online_check(max_checks=10, current_check=0):
    try:
        con = urllib2.urlopen("http://www.google.com/")
        data = con.read()
        logging.debug('{0} Reached the host. Exiting online_check'.format(time.strftime('[ %H:%M:%S ]')))
    except:
        logging.debug('{0} Could not reach host trying again in 3 seconds'.format(time.strftime('[ %H:%M:%S ]')))
        if max_checks > current_check:
          time.sleep(3)
          online_check(max_checks, current_check+1)

所以你会这样做:

online_check(5) # for 5 maximum checks
online_check() # use the default value, which is 10

我还建议您捕获更多特定的异常,以获得更好的编码习惯,但也因为当您执行CTRL-C时,Python会抛出一个KeyboardInterrupt异常,您的代码实际捕获该异常,因为您捕获了所有异常。

答案 1 :(得分:3)

除了无限递归(CPython,据我所知不支持优化的尾端递归),你没有关闭你的连接。

您可能会在重试时与操作系统或Google达成某种连接限制。这可能在达到最大递归深度之前发生,这就是为什么你没有得到异常。

连接通常会在收集垃圾时关闭,但我认为由于递归,变量在递归结束之前不会完全超出范围。

同样@senderle提到,你应该尝试捕捉更具体的错误。

尝试:

def online_check():
  while True:
    try:
      con = urllib2.urlopen("http://www.google.com/")
      data = con.read()
      logging.debug('{0} Reached the host. Exiting online_check'.format(time.strftime('[ %H:%M:%S ]')))
    except urllib2.URLError:
      logging.debug('{0} Could not reach host trying again in 3 seconds'.format(time.strftime('[ %H:%M:%S ]')))
      time.sleep(3)
    finally:
      con.close()

(警告未经测试的代码)

答案 2 :(得分:2)

除了别人的建议之外,你应该真正指明你正在捕捉哪些例外。 Control-C不起作用,因为它只是引发异常,而你的except语句将其解释为与所有其他语句相同。

似乎您想要的例外是urllib2.URLError

答案 3 :(得分:1)

在某些时候,这个程序最终会遇到解释器的递归深度限制。通常,应该连续运行的函数的结构如下:

def online_check():
  while True:
    try:
      con = urllib2.urlopen("http://www.google.com/")
      data = con.read()
      logging.debug('{0} Reached the host. Exiting online_check'.format(time.strftime('[ %H:%M:%S ]')))
      break
    except:
      logging.debug('{0} Could not reach host trying again in 3 seconds'.format(time.strftime('[ %H:%M:%S ]')))
      time.sleep(3)

这应该会给你更好的结果。我想你已经有了一个运行这个函数的独立线程(否则后来的代码无法执行 - 这个函数永远不会返回)。