<p>好吧,首先,有几点不能直接回答你的问题,但可能会有帮助:</p>
<p>1)我确信在调用urllib2.urlopen和读取返回的addinfourl对象之间不需要等待。在<a href="http://docs.python.org/library/urllib2.html#examples" rel="nofollow">http://docs.python.org/library/urllib2.html#examples</a>的例子中没有任何这样的睡眠。</p>
<p>2个)</p>
<pre><code>json.loads(urlobject.read().decode("utf-8"))
</code></pre>
<p>可以简化为</p>
<pre><code>json.load(urlobject)
</code></pre>
<p>更简单易读。
基本上,.load使用类似文件的对象作为参数,而.load使用字符串。您可能认为有必要先读取()数据,以便从utf-8对其进行解码,但事实上这没有问题,因为.load默认假定它读取的对象是ascii或utf-8编码的(请参见<a href="http://docs.python.org/library/json.html#json.load" rel="nofollow">http://docs.python.org/library/json.html#json.load</a>)。</p>
<p>3)对于您目前的目的,这可能不重要,但我认为您在这里的异常处理是糟糕的。如果在“try:”块中出现任何错误,那么将不会分配变量jsondata。然后,当尝试在try/except块结束后返回时,由于尝试使用未分配的变量,将引发NameError。这意味着,如果应用程序中的其他某个函数调用returnJSONQuestion并发生异常,则外部函数看到的将是NameError,而不是原始异常,并且外部函数生成的任何回溯都不会指向实际问题发生的位置。这很容易在试图找出哪里出了问题时引起混乱。因此,如果你所有的“除了”积木都用“raise”完成,那就更好了。</p>
<p>4)在Python中,最好在函数上方添加注释,说明函数作为docstring(请参见<a href="http://www.python.org/dev/peps/pep-0257/#what-is-a-docstring" rel="nofollow">http://www.python.org/dev/peps/pep-0257/#what-is-a-docstring</a>)的作用,而不是作为注释。</p>
<p>无论如何,要真正回答你的问题。。。</p>
<p>由于各种原因尝试打开URL时,可能会出现看似随机的URLError。可能是服务器在处理您的请求时出现了一个bug;可能是连接问题和一些数据丢失;可能是服务器在某个管理员更改设置或推送更新时关闭了几秒钟;可能是完全其他的问题。在做了一点web开发之后,我注意到一些服务器比其他服务器更可靠,但是我想对于大多数现实世界来说,您可能不需要担心为什么。最简单的方法就是重试请求直到成功。</p>
<p>考虑到以上所有因素,下面的代码可能会满足您的需要:</p>
<pre><code>def returnJSONQuestion(questionId):
"""return the json question for given question id"""
url = 'http://answers.yahooapis.com/AnswersService/V1/getQuestion?appid=APPIDREMOVED8&question_id={0}&output=json'
format_url = url.format(questionId)
try:
request = urllib2.Request(format_url)
# Try to get the data and json.load it 5 times, then give up
tries = 5
while tries >= 0:
try:
urlobject = urllib2.urlopen(request)
jsondata = json.load(urlobject)
print jsondata
return jsondata
except:
if tries == 0:
# If we keep failing, raise the exception for the outer exception
# handling to deal with
raise
else:
# Wait a few seconds before retrying and hope the problem goes away
time.sleep(3)
tries -= 1
continue
except urllib2.HTTPError, e:
print e.code
logging.exception("Exception")
raise
except urllib2.URLError, e:
print e.reason
logging.exception("Exception")
raise
except(json.decoder.JSONDecodeError,ValueError):
print 'Question ID ' + questionId + ' Decode JSON has failed'
logging.info("This qid didn't work " + questionId)
raise
</code></pre>
<p>希望这有帮助!如果您要在程序中发出许多不同的web请求,您可能需要将这个“异常时重试请求”逻辑抽象到某个函数中,这样就不需要将样板重试逻辑与其他内容混合在一起。:)</p>