ValueError: неверно сформированная строка с использованием ast.literal_eval

Я делаю цикл, чтобы получить JSON API, вот что у меня в цикле:

response_item = requests.request('GET',url_item,params=None,verify=False)
response_item = json.loads(response_item.text)
response_item = ast.literal_eval(json.dumps(response_item, ensure_ascii=False).encode('utf8'))

Я сканирую около 45000 объектов JSON, я генерирую переменную "url_item" для каждой итерации. Каждый объект один и тот же, я могу получить что-то вроде объекта 7000, и у меня появляется следующая ошибка, когда я достигаю 7064-го:

Traceback (most recent call last):
  File "C:\Python27\tools\api_item.py", line 47, in <module>
    response_item = ast.literal_eval(json.dumps(response_item, ensure_ascii=False).encode('utf8'))
  File "C:\Python27\lib\ast.py", line 80, in literal_eval
    return _convert(node_or_string)
  File "C:\Python27\lib\ast.py", line 63, in _convert
    in zip(node.keys, node.values))
  File "C:\Python27\lib\ast.py", line 62, in <genexpr>
    return dict((_convert(k), _convert(v)) for k, v
  File "C:\Python27\lib\ast.py", line 63, in _convert
    in zip(node.keys, node.values))
  File "C:\Python27\lib\ast.py", line 62, in <genexpr>
    return dict((_convert(k), _convert(v)) for k, v
  File "C:\Python27\lib\ast.py", line 79, in _convert
    raise ValueError('malformed string')
ValueError: malformed string

Я использовал для печати второй и третий "response_item". Конечно, в этом случае третий не отображается, так как у меня есть ошибка как раз перед этим, вот что я имею для печати после json.load:

{u'restrictions': [], u'name': u'Sac \xe0 dos de base', u'level': 0, u'rarity': u'Basic', u'vendor_value': 11, u'details': {u'no_sell_or_sort': False, u'size': 20}, u'game_types': [u'Activity', u'Wvw', u'Dungeon', u'Pve'], u'flags': [u'NoSell', u'SoulbindOnAcquire', u'SoulBindOnUse'], u'icon': u'https://render.guildwars2.com/file/80E36806385691D4C0910817EF2A6C2006AEE353/61755.png', u'type': u'Bag', u'id': 8932, u'description': u'Un sac de 20 emplacements pour les personnages d\xe9butants.'}

Каждый предмет, который я получаю до этого, имеет тот же тип, тот же формат, и у меня нет никаких ошибок, кроме 7064-го!

Спасибо за помощь!

2 ответа

Решение

Вы не должны использовать ast.literal_eval() на данных JSON. Литералы JSON и Python могут выглядеть как одно и то же, но это не так.

В этом случае ваши данные содержат логический флаг, установленный на false в формате JSON. Правильный логин Python использует title-case, поэтому False:

>>> import json, ast
>>> s = '{"no_sell_or_sort": false, "size": 20}'
>>> json.loads(s)
{u'no_sell_or_sort': False, u'size': 20}
>>> ast.literal_eval(s)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/mj/Development/Library/buildout.python/parts/opt/lib/python2.7/ast.py", line 80, in literal_eval
    return _convert(node_or_string)
  File "/Users/mj/Development/Library/buildout.python/parts/opt/lib/python2.7/ast.py", line 63, in _convert
    in zip(node.keys, node.values))
  File "/Users/mj/Development/Library/buildout.python/parts/opt/lib/python2.7/ast.py", line 62, in <genexpr>
    return dict((_convert(k), _convert(v)) for k, v
  File "/Users/mj/Development/Library/buildout.python/parts/opt/lib/python2.7/ast.py", line 79, in _convert
    raise ValueError('malformed string')
ValueError: malformed string

Другие различия включают использование null вместо Noneи escape-последовательности Unicode в том, что для Python 2 выглядит как простая (байтовая) строка, с использованием суррогатов UTF-16 при экранировании кодовых точек, отличных от BMP.

Загрузите ваши данные с json.loads()не ast.literal_eval(), Он не только отлично справится с правильным JSON, но и быстрее.

В вашем случае, кажется, вы используете json.dumps() затем попробуйте снова загрузить данные ast.literal_eval(), В этом шаге нет необходимости, у вас уже есть объект Python.

Другими словами, строка:

response_item = ast.literal_eval(json.dumps(response_item, ensure_ascii=False).encode('utf8'))

в лучшем случае избыточно, а в худшем - очень, очень неправильно. Повторное кодирование response_item для строки JSON не создает чего-то, что может быть интерпретировано как литерал Python.

ast.literal_eval безопасен с SQL-инъекцией, если вы используете это. потому что, когда вставляется нежелательный чартер, он показывает ошибку Syntex, которая предотвращает инъекцию.

Другие вопросы по тегам