ValueError:使用ast.literal_eval的格式错误的字符串

Aur*_*ien 6 python string json malformed python-requests

我正在做一个循环来获取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'))
Run Code Online (Sandbox Code Playgroud)

我扫描45000个json对象,我为每次迭代生成"url_item"变量.每个对象都是一样的,我可以得到像7000对象的东西,当我到达7064th时我有以下错误:

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
Run Code Online (Sandbox Code Playgroud)

我曾经打印过第二个和第三个"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.'}
Run Code Online (Sandbox Code Playgroud)

我在此之前获得的每个项目都具有相同的类型,相同的格式,除了7064th之外我没有任何错误!

谢谢您的帮助!

Mar*_*ers 26

你应该使用ast.literal_eval()的JSON数据.JSON和Python文字看起来可能是一样的,但它们并非如此.

在这种情况下,您的数据包含一个布尔标志,设置为falseJSON.一个合适的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
Run Code Online (Sandbox Code Playgroud)

其他差异包括使用null而不是None和Unicode转义序列在Python 2中看起来像普通(字节)字符串,在转义非BMP代码点时使用UTF-16代理.

加载数据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'))
Run Code Online (Sandbox Code Playgroud)

在最坏的情况下,充其量是多余的,非常非常错误.重新编码response_item为JSON字符串不会产生可以解释为Python文字的内容.

  • @Kroltan:`ast.literal_eval()`非常安全.它将字符串解析为抽象语法树,然后仅将文字(字符串,列表,数字等)映射到Python对象.其他一切都引发了异常. (2认同)
  • 我已经删除了你告诉我的ast.literal_eval()行.现在我没有错误,但我有unicode字符"你"的东西,我已经尝试过多次删除这些字符,因为它们被插入数据库然后.这就是为什么我添加了这行的原因.. (2认同)