Python запрашивает случайные разрывы с JSONDecodeError

1

Я отлаживал часами, почему мой код случайно разбивается с этой ошибкой: JSONDecodeError: Expecting value: line 1 column 1 (char 0)

Это код, который у меня есть:

while True:
    try:
        submissions = requests.get('http://reymisterio.net/data-dump/api.php/submission?filter[]=form,cs,'+client+'&filter[]=date,cs,'+since).json()['submission']['records']
        break
    except requests.exceptions.ConnectionError:
        time.sleep(100)

И я отлаживаю, печатая requests.get(url) и requests.get(url).text и я столкнулся со следующими "специальными" случаями:

  1. requests.get(url) возвращает успешный ответ 200 и requests.get(url).text возвращает html. Я читал в Интернете, что это не requests.get(url).json() при использовании requests.get(url).json(), потому что он не сможет прочитать html, но как-то он не сломается. Почему это?

  2. requests.get(url) возвращает успешный ответ 200, а requests.get(url).text находится в формате json. Я не понимаю, почему, когда он идет на requests.get(url).json() она ломается с JSONDecodeError?

Точное значение requests.get(url).text для случая 2:

{
  "submission": {
    "columns": [
      "pk",
      "form",
      "date",
      "ip"
    ],
    "records": [
      [
        "21197",
        "mistico-form-contacto-form",
        "2018-09-21 09:04:41",
        "186.179.71.106"
      ]
    ]
  }
}
  • 0
    это работает при попытке json.loads(requests.get(url).text) ?
Теги:
python-requests
jsondecoder

1 ответ

0

Глядя на документацию по этому API, кажется, что единственные ответы в формате JSON, поэтому получение HTML странно. Чтобы увеличить вероятность получения ответа JSON, вы можете настроить заголовок "Принять" на "application/json".

Я пробовал многократно запрашивать этот API с параметрами и не сталкивался с JSONDecodeError. Вероятно, эта ошибка является результатом другой ошибки на стороне сервера. Чтобы справиться с этим, за except того, в json.decoder.JSONDecodeError в дополнение к ConnectionError ошибка, которую вы в настоящее время, за except и обрабатывать эту ошибку таким же образом, как ConnectionError.

Вот пример с учетом всего этого:

import requests, json, time, random

def get_submission_records(client, since, try_number=1):
    url = 'http://reymisterio.net/data-dump/api.php/submission?filter[]=form,cs,'+client+'&filter[]=date,cs,'+since
    headers = {'Accept': 'application/json'}
    try:
        response = requests.get(url, headers=headers).json()
    except (requests.exceptions.ConnectionError, json.decoder.JSONDecodeError):
        time.sleep(2**try_number + random.random()*0.01) #exponential backoff
        return get_submission_records(client, since, try_number=try_number+1)
    else:
        return response['submission']['records']

Я также обернут эта логика в рекурсивной функции, а не использовать во while цикла, потому что я думаю, что это семантический яснее. Эта функция также ждет, прежде чем повторять попытку с помощью экспоненциального отсрочка (ожидание в два раза больше после каждого отказа).

Изменить: для Python 2.7 ошибка при попытке разобрать bad json - это ValueError, а не JSONDecodeError

import requests, time, random

def get_submission_records(client, since, try_number=1):
    url = 'http://reymisterio.net/data-dump/api.php/submission?filter[]=form,cs,'+client+'&filter[]=date,cs,'+since
    headers = {'Accept': 'application/json'}
    try:
        response = requests.get(url, headers=headers).json()
    except (requests.exceptions.ConnectionError, ValueError):
        time.sleep(2**try_number + random.random()*0.01) #exponential backoff
        return get_submission_records(client, since, try_number=try_number+1)
    else:
        return response['submission']['records']

поэтому просто измените это, except строки, чтобы включить ValueError вместо json.decoder.JSONDecodeError.

  • 0
    да, я был очень смущен, когда я получал вывод html. Спасибо ! этот пример выглядит отлично, я попробую. надеюсь, что параметр заголовка исправит это.
  • 0
    Я тестировал эту реализацию и получаю эту ошибку: AttributeError: у объекта 'module' нет атрибута 'JSONDecodeError'. Я использую Python 2.7, это из-за этого?
Показать ещё 4 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню