我有一些代码,嗯,从给定的URL获取页面。
在try / except子句中,如果发生异常,程序会休眠几秒钟,打印回溯,然后再次递归启动。
def fetch_page(self, url):
head = {'User-agent': "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:42.0) Gecko/20100101 Firefox/42.0"}
time.sleep(2)
print "..."
try:
r = requests.get(url, headers=head)
except:
time.sleep(2)
print 'error', url, "Trying again"
traceback.print_exc()
self.fetch_page(url)
r.raise_for_status()
print r.status_code
return r.text
但是每当发生异常时,代码会成功休眠,进行递归调用,打印r.status_code
,然后在UnboundLocalError
上提供r.raise_for_status()
。
...
200
Traceback (most recent call last):
File "./calling.py", line 140, in <module>
get_valid_url = Get()
File "./calling.py", line 22, in __init__
self.call()
File "./calling.py", line 44, in call
text = self.fetch_page(link.strip('\n'))
File "./calling.py", line 35, in fetch_page
r.raise_for_status()
UnboundLocalError: local variable 'r' referenced before assignment
现在,如果在分配之前引用r
,为什么要打印r.status_code
?
我的第一个猜测可能是我搞砸了递归电话。但这没有任何意义。我错过了什么?
答案 0 :(得分:2)
想象一下,你运行你的功能并第一次获得404。您输入except
块,然后再次递归调用fetch_page
。假设你这次得到200分。您没有输入except
块;相反,您将运行到函数的末尾并return r.text
。
Control返回到调用者,这是您之前调用的fetch_page
。执行下一行代码r.raise_for_status()
。但是在 {/ 1}}(顶层)的调用中,fetch_page
从未实际定义过,因为r
块中抛出了异常。因此,try
。
一种可能的解决方案 - 而不是:
UnboundLocalError
将递归调用的结果返回except:
time.sleep(2)
print 'error', url, "Trying again"
traceback.print_exc()
self.fetch_page(url)
:
fetch_page
我还建议你做一些更像这样的事情,这样你就可以避免在不同的缩进级别获得回报:
except:
time.sleep(2)
print 'error', url, "Trying again"
traceback.print_exc()
return self.fetch_page(url)