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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32695699/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 12:05:42  来源:igfitidea点击:

ValueError: malformed string using ast.literal_eval

pythonjsonstringpython-requestsmalformed

提问by Aurélien

I'm doing a loop to get json api, here is what I have in my loop:

我正在做一个循环来获取 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'))

I scan around 45000 json objects, I generate "url_item" variable for each iteration. Each object is the same, I can get something like 7000 object and I have the following error when I reach the 7064th:

我扫描了大约 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

I used to print the second and third "response_item". Of course in this case the third one isn't displayed since I have the error just before, here what I have for the print after the json.load:

我曾经打印第二个和第三个“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.'}

Every item I get before this one has the same type, same format, and I don't have any error except for the 7064th !

在这之前我得到的每件物品都具有相同的类型、相同的格式,除了第 7064 个之外,我没有任何错误!

Thank you for your help!

感谢您的帮助!

采纳答案by Martijn Pieters

You should notuse ast.literal_eval()on JSON data. JSON and Python literals may looklike the same thing, but they are very much not.

你应该使用ast.literal_eval()的JSON数据。JSON 和 Python 文字可能看起来是一回事,但实际上并非如此。

In this case, your data contains a boolean flag, set to falsein JSON. A proper Python boolean uses title-case, so False:

在这种情况下,您的数据包含一个布尔标志,false在 JSON 中设置为。正确的 Python 布尔值使用标题大小写,因此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

Other differences include using nullinstead of None, and Unicode escape sequences in what to Python 2 looks like a plain (bytes) string, using UTF-16 surrogates when escaping non-BMP codepoints.

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

Load your data with json.loads(), not ast.literal_eval(). Not only will it handle proper JSON just fine, it is also faster.

加载您的数据json.loads(),而不是ast.literal_eval()。它不仅可以很好地处理正确的 JSON,而且速度更快

In your case, it appears you are using json.dumps()then try to load the data again with ast.literal_eval(). There is no needfor that step, you alreadyhad a Python object.

在您的情况下,您似乎正在使用,json.dumps()然后尝试使用ast.literal_eval(). 有没有必要进行这一步,你已经有一个Python对象。

In other words, the line:

换句话说,该行:

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

is redundant at best, and very, very wrong, at worst. Re-encoding response_itemto a JSON string does not produce something that can be interpreted as a Python literal.

充其量是多余的,最糟糕的是非常非常错误。重新编码response_item为 JSON 字符串不会产生可以解释为 Python 文字的内容。

回答by Sajid

ast.literal_eval is safe with SQL injection if you are using this. because when an unwanted charter is inserted it will show Syntex error which prevents from an injection.

如果你正在使用它,ast.literal_eval 对 SQL 注入是安全的。因为当插入不需要的章程时,它会显示 Syntex 错误,从而防止注入。