2017-09-26 19 views
0

我正在創建一個簡單的程序,它接受來自Bitstamp.net API的'最後'值並使用它。見下面的代碼。API請求期間零星的JSONDecodeError

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) 

回答

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."') 

原來的答案

當你說你03分鐘或數小時後得到的錯誤,你的意思是代碼運行,等待持續3分鐘或幾個小時,然後拋出錯誤?這聽起來像是一個超時問題,這意味着如果一個URL在X秒內沒有響應,它將返回一個504錯誤,但我認爲它會持續60秒或180秒。我建議使用郵遞員發出請求並查看錯誤響應。或者更好的辦法是打印出當前代碼中的錯誤,或者在出錯時輸入pdb.set_trace()。

你得到的錯誤是因爲requests.get(url)失敗,這意味着r.textNone,這會導致你的priceFloat線錯誤。換句話說,堆棧跟蹤中的最後一行raise JSONDecodeError("Expecting value", s, err.value) from None...意味着json.loads()正在傳遞None而不是值。作爲一個經驗法則,如果你得到一個錯誤,但不是所有的時間,它是一個race condition,這是'輸出依賴於其他不可控事件的順序或時間。當事件沒有按照程序員的意圖發生時,它就成了一個錯誤。「

+0

感謝您的信息。代碼從API獲取當前值,然後將其存儲在列表變量中。它每5秒鐘完成一次。該程序將每5秒運行一次,並添加新值,但隨後會因此錯誤而崩潰。所以,它似乎不是超時問題。我認爲這可能是一個與網站有關的問題,但每次檢查代碼時,這些值都顯示正常。 – paulK

+0

在您的'except'子句中,輸出'r'的值以及您從API獲取的響應。答案將是一個400或更高的HTML代碼(400秒是客戶端錯誤,500秒是服務器錯誤),最有可能的。 您也可以使用Selenium抓取錯誤截圖。見[這個SO問題](https:// stackoverflow。com/questions/37608768 /執行例外截圖)以獲取更多信息。 –

+0

好的建議。我會現在做,然後看看我運行它時得到的結果。 – paulK

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 

如果有人有更優雅的解決方案,請告訴我! :)

+0

查看我的原始答案,我用我的建議更新了它。 –