API请求期间偶发的JSONDecodeError

时间:2017-09-26 18:32:35

标签: python json api

我正在创建一个简单的程序,它从Bitstamp.net API获取'last'值并使用它。见下面的代码。

def getBitcoinPrice():

    url = 'https://www.bitstamp.net/api/ticker/'
    try:
        r = requests.get(url)
        priceFloat = float(json.loads(r.text)['last'])
        return priceFloat
    except requests.ConnectionError:
        print("Error querying Bitstamp API")
        os.system('say "The program broke."')

我会在3分钟后得到零星的JSONDecodeError,其他时间会在几个小时后得到。我到处寻找,无法弄清楚这一点。请参阅下面的错误。非常感谢任何帮助!

File "/Users/paulkaraffa/PycharmProjects/socialbitanalytics/actionEvaluator.py", line 70, in <module>
    btcValues.append(getBitcoinPrice())

File "/Users/paulkaraffa/PycharmProjects/socialbitanalytics/actionEvaluator.py", line 26, in getBitcoinPrice
    priceFloat = float(json.loads(r.text)['last'])

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/__init__.py", line 354, in loads
    return _default_decoder.decode(s)

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/decoder.py", line 339, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/decoder.py", line 357, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

2 个答案:

答案 0 :(得分:0)

更新:建议解决方案

def getBitcoinPrice():

    url = 'https://www.bitstamp.net/api/ticker/'
    try:
        r = requests.get(url, timeout=60)
        priceFloat = float(json.loads(r.text)['last'])
        return priceFloat
    except json.decoder.JSONDecodeError:
        # wait 5 seconds and try again. This would require you to put your try block 
        # into it's own function so you can more easily call it here in the exception.
    else:
        print("Error querying Bitstamp API")
        os.system('say "The program broke."')

原始答案

当你说你在3分钟或几个小时后收到错误时,你的意思是代码运行,等待3分钟或几个小时,然后抛出错误?这听起来像是一个超时问题,这意味着如果一个URL在X秒内没有响应,它将返回504错误,但我希望它是一个60秒或180秒的一致。我建议使用Postman发出请求并查看错误响应。或者更好的方法是在当前代码中打印出错误,或者在出错时输入pdb.set_trace()。

您收到的错误是因为requests.get(url)失败,这意味着r.textNone,导致您的priceFloat行出错。换句话说,堆栈跟踪中的最后一行raise JSONDecodeError("Expecting value", s, err.value) from None...表示json.loads()正在传递None而不是值。

根据经验,如果你得到一个错误而不是所有的时间,那么它是race condition,这是&#39;其中输出取决于其他不可控的序列或时间事件。当事件没有按程序员的意图发生时,它就会成为一个错误。&#39;

答案 1 :(得分:0)

所以,我想出了一个解决方案,虽然我不确定它是最优雅的解决方案。杰森是正确的,这是一个超时错误。我更改了以下代码:

r = requests.get(url)

r = requests.get(url, timeout=120.0)

通过进行此更改,错误大部分消失了。但是,我需要在仍然填充此值的except子句中添加代码。为此,我在定义getBitcoinPrice()之前添加了一个单独的request.get,它为我提供了这种情况的值。代码如下所示:

urlException = 'https://www.bitstamp.net/api/ticker/'
r = requests.get(urlException, timeout=600.0)
exceptionValue = float(json.loads(r.text)['last'])
print(exceptionValue)

def getBitcoinPrice():
    url = 'https://www.bitstamp.net/api/ticker/'
    try:
        r = requests.get(url, timeout=120.0)
        priceFloat = float(json.loads(r.text)['last'])
        return priceFloat

    except requests.ConnectionError:
        print("Error querying Bitstamp API")
        return exceptionValue

如果有人有更优雅的解决方案,请告诉我们! :)