add*_*ons 0 python json urllib2 httprequest
我正在使用 Yahoo Api,除了我添加了硬睡眠之外,我还实现了随机睡眠方法,但我仍然无法弄清楚如果我在第一次尝试时没有得到响应,我该如何等待或再试一次。
例如,我在下面放置的代码完全随机地在某些用户处失败。失败后,我在浏览器上获取 url,它就像一个魅力。所以我的问题是为什么?我该如何解决这个问题?或者我可以改进此代码以在沉睡后执行另一个请求(仅当这是一个好方法时)
我忘记添加更多信息,我更改了代码以获取我的 http 成功代码:
print urlobject.getcode()
Run Code Online (Sandbox Code Playgroud)
它返回 200,但没有 json,因为有人建议这可能是油门。
注意:我已经从 url 中删除了我的 appid(Key)
# return the json question for given question id
def returnJSONQuestion(questionId):
randomSleep()
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)
urlobject = urllib2.urlopen(request)
time.sleep(10)
jsondata = json.loads(urlobject.read().decode("utf-8"))
print jsondata
except urllib2.HTTPError, e:
print e.code
logging.exception("Exception")
except urllib2.URLError, e:
print e.reason
logging.exception("Exception")
except(json.decoder.JSONDecodeError,ValueError):
print 'Question ID ' + questionId + ' Decode JSON has failed'
logging.info("This qid didn't work " + questionId)
return jsondata
Run Code Online (Sandbox Code Playgroud)
好的,首先,有几点不能直接回答您的问题,但可能会有所帮助:
1) 我很确定在调用 urllib2.urlopen 和读取返回的 addinfourl 对象之间永远不需要等待。http://docs.python.org/library/urllib2.html#examples 上的示例没有任何此类睡眠。
2)
json.loads(urlobject.read().decode("utf-8"))
Run Code Online (Sandbox Code Playgroud)
可以简化为
json.load(urlobject)
Run Code Online (Sandbox Code Playgroud)
这更简单,更具可读性。基本上, .load 接受一个类似文件的对象作为参数,而 .loads 接受一个字符串。您可能认为必须先 read() 数据才能从 utf-8 解码,但这实际上没有问题,因为 .load 默认假定它正在读取的对象是 ascii 或 utf- 8 编码(参见http://docs.python.org/library/json.html#json.load)。
3)对于您目前的目的而言,这可能无关紧要,但我认为您在这里的异常处理很糟糕。如果在“try:”块期间出现任何问题,则变量 jsondata 将不会被分配。然后,当我们尝试在 try/except 块结束后返回它时,由于尝试使用未分配的变量,将引发 NameError。这意味着,如果您的应用程序中的某个其他函数调用 returnJSONQuestion 并且发生异常,那么它将是一个 NameError,而不是外部函数看到的原始异常,并且外部函数生成的任何回溯都不会指向该位置真正的问题出现了。在试图找出出了什么问题时,这很容易引起混淆。因此,如果您所有的“except”块都以“raise”结束,那就更好了。
4) 在 Python 中,最好用注释来说明函数的作用作为文档字符串(参见http://www.python.org/dev/peps/pep-0257/#what-is-a-docstring)而不是作为函数上方的注释。
无论如何,要真正回答您的问题......
出于各种原因尝试打开 URL 时,您可能会收到看似随机的 URLError。可能在处理您的请求期间服务器上存在错误;可能是连接有问题,一些数据丢失了;也许服务器停机了几秒钟,而其中一位管理员更改了设置或推送了更新;也许完全是别的东西。在进行了一些 Web 开发后,我注意到有些服务器比其他服务器可靠得多,但我认为对于大多数实际用途,您可能不需要担心原因。最简单的方法就是重试请求,直到成功。
考虑到上述所有内容,下面的代码可能会满足您的需求:
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
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助!如果你打算在你的程序中发出很多不同的 Web 请求,你可能想把这个“异常重试请求”逻辑抽象到某个地方的一个函数中,这样你就不需要样板重试了逻辑与其他东西混合在一起。:)
归档时间: |
|
查看次数: |
17903 次 |
最近记录: |