Python eval vs ast.literal_eval против декодирования JSON

Я преобразовываю 2 МБ данных в виде строки в dict. Вход сериализуется в JSON.

В любом случае я в настоящее время использую ast.literal_eval, и я получаю словарь, который я хочу, но тогда, когда я пробовал только запустить eval, он работает быстрее, а также возвращает тот же результат.

Есть ли причина использовать модуль ast или модуль json, когда eval работает просто отлично?

Ответ 1

Да, там определенно причина: eval() - зло. В один прекрасный день ваш код может прочитать ненадежные данные, это позволит злоумышленнику запускать на вашем компьютере произвольный код.

Вы не должны использовать ast.literal_eval() для декодирования JSON. Он не может декодировать каждую допустимую строку JSON и не предназначен для использования для этой цели. Просто используйте json.loads(), это достаточно быстро.

Ответ 2

Мне не нравится это отношение к stackoverflow (и в другом месте), говорящим людям без какого-либо контекста, что то, что они делают, небезопасно, и они не должны этого делать. Может быть, это просто выброс script для импорта некоторых данных, в этом случае почему бы не выбрать самый быстрый или удобный способ?

В этом случае, однако, json.loads не только более безопасен, но и более чем в 4 раза быстрее (в зависимости от ваших данных).

In [1]: %timeit json.loads(data)
10000 loops, best of 3: 41.6 µs per loop

In [2]: %timeit eval(data)
10000 loops, best of 3: 194 µs per loop

In [3]: %timeit ast.literal_eval(data)
1000 loops, best of 3: 269 µs per loop

Если вы думаете, что это имеет смысл, json - такой более ограниченный язык/формат, чем python, поэтому он должен быстрее анализировать оптимизированный синтаксический анализатор.

Ответ 3

Нет. Если вы не нажмете один из двух сценариев:

  • Это не JSON!

    Кто-то помещает __import__('os').system('rm -rf /') в файл. Вы бонитесь.

  • Это JSON, но не часть, подобная Python!

    Кто-то ставит true, false, null или вытесняет Unicode где-то в нем. С днем ​​рождения.

Ответ 4

eval подвержен угрозам безопасности. Используйте только тогда, когда вы абсолютно контролируете, что получает eval'ed

Ответ 5

Не ответ точно, но следует отметить, что eval и literal_eval - это не одно и то же. ast.literal_eval не будет запускать произвольный код.

Тем не менее, я согласен с использованием JSON; Я просто хотел указать, что eval != literal_eval