Оболочка Python для API ценообразования

#python #python-3.x

Вопрос:

Я написал оболочку python для API ценообразования. В конце моего кода я выполняю вызовы метода к конечным точкам API. Существует 4 различных конечных точки API. Когда я выполняю тестовый запуск и попадаю в конечные точки, 3 из 4 конечных точек возвращают ответ JSON, за исключением третьего, называемого «test3». Может быть, это то, как я отформатировал URL-ответ в своей строке f? Я попытался отформатировать его по-другому, но все равно продолжаю получать эту ошибку.

Ошибка здесь: описание изображения находится здесь

 import http.client
import urllib.request, urllib.parse, urllib.error
import json
import base64

 
def loadJson(response):
   body = response.read()
   if body == "" or body is None:
       print(("Empty response found with status "   str(response.status)))
       return {}
   else:
       return json.loads(body)
 
class data_pricing_client:
 
   def __init__(self, host, clientId, clientSecret):
       conn = http.client.HTTPSConnection("sso.lukka.tech")
       path = "/oauth2/aus1imo2fqcx5Ik4Q0h8/v1/token"
       encodedData = base64.b64encode(bytes(f"{clientId}:{clientSecret}", "ISO-8859-1")).decode("ascii")
       authHeader = "Basic "   encodedData
       headers = {
           "Authorization": authHeader,
           "Accept": "application/json",
           "Content-Type": "application/x-www-form-urlencoded"
       }
       params = urllib.parse.urlencode({
           "grant_type": "client_credentials",
           "scope": "pricing"
       })
 
       conn.request("POST", path, params, headers)
       response = conn.getresponse()
 
       if response.status != 200:
           raise ApiErrorException(response.status, "Failed to get access token")
 
       self.host = host
       self.accessToken = loadJson(response)["access_token"]
 
   def default_headers(self):
       return {
           "Content-Type": "application/json",
           "Accept": "application/json",
           "Authorization": "Bearer "   self.accessToken
       }
  
   def send_message(self,path):
       conn = http.client.HTTPSConnection(self.host)
       headers = self.default_headers()
       conn.request("GET", path, None, headers)
       response_json = loadJson(conn.getresponse())
       conn.close()
       return response_json
 
   def get_available_sources(self):
       path = "/v1/pricing/sources"
       return self.send_message(path)
 
   def get_source_details(self, sourceId):
       path = f"/v1/pricing/sources/{sourceId}/prices"
       return self.send_message(path)
 
   def get_latest_prices(self, sourceId, pairCodes=None, asOf=None, variances=False):
       query_params = {
           "pairCodes":pairCodes,
           "asOf":asOf
       }
       path = f"/v1/pricing/sources/{sourceId}/prices/{'/variances' if variances else ''}?{urllib.parse.urlencode({k: v for k, v in query_params.items() if v is not None})}"
       print(path)
       return self.send_message(path)
  
   def get_historical_prices(self, sourceId, pairCode, from_ts=None, to_ts=None, fill=None, limit=None, variances=False):
       query_params = {
           "from":from_ts,
           "to":to_ts,
           "fill": fill,
           "limit": limit
       }
       path = f"/v1/pricing/sources/{sourceId}/prices/pairs/{pairCode}{'/variances' if variances else ''}?{urllib.parse.urlencode({k: v for k, v in query_params.items() if v is not None})}"
       print(path)
       return self.send_message(path)
 
       
 
class ApiErrorException(Exception):
   def __init__(self, status, msg):
       self.msg = "Error "   str(status)   ": "   msg
   def __str__(self):
       return self.msg
 
if __name__ == '__main__':
   from pricing_api_creds import lukka_pricing
   c = data_pricing_client(**lukka_pricing)

   test1 = c.get_available_sources()
   test1 = c.send_message("/v1/pricing/sources")
   print(test1)

   test2 = c.get_source_details(3000)
   test2 = c.send_message("/v1/pricing/sources/")
   print(test2)

   test3 = c.get_latest_prices(3000)
   test3 = c.send_message("v1/pricing/sources/1000/prices")
   print(test3)
 
   test4 = c.get_historical_prices(1000, "XBT-USD",)
   test4=c.send_message("/v1/pricing/sources/1000/prices/pairs/XBT-USD")
   print(test4)
 

Комментарии:

1. Вы получаете ответ, который не является json

2. Ваш код выглядит нормально — это ответ от этой конкретной конечной точки API, которая либо не является JSON, либо неправильно сформирована JSON. Чтобы быть точным, просмотр исключения указывает на то, что ответ пустой («Ожидаемое значение: строка 1, столбец 1 (символ: 0)»), поэтому вы пытаетесь проанализировать JSON из пустой строки.

3. Тем не менее, ваш код, вероятно, все еще является виновником, для нас просто невозможно сказать, что именно не так, не зная, что такое API. Убедитесь, что URL-адрес конечной точки, который вы создаете с помощью f-строки, правильный, и что параметры строки запроса правильные.

4. Для всех, кому интересно, похоже, что это конечная точка API , о которой идет речь.

5. Может ли быть так , что запрос недействителен, потому что URL конечной точки содержит конечную ? строку, но не содержит параметров строки запроса? Попробуйте удалить ? параметры строки запроса «При передаче» и посмотрите, получите ли вы ответ…

Ответ №1:

Вы можете видеть, что ошибка возникает из JSONDecoder. Возможно, ответ поврежден или ответ не является допустимым Json, который можно сопоставить. Попробуйте зарегистрировать ответ, чтобы получить более подробное представление о нем.