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