在我的一个脚本中,我使用以下无限循环来检查有效的互联网连接:
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:如果您有设计方法来检查连接而不使用带宽和最小开销,我会非常乐意听到它。
答案 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)
这应该会给你更好的结果。我想你已经有了一个运行这个函数的独立线程(否则后来的代码无法执行 - 这个函数永远不会返回)。