Использование ast.literal_eval(...)
будет работать, но для него требуется специальный синтаксис, который не распознается другими программами для чтения CSV, и используют оператор eval
, который является красным флагом.
Использование eval может быть опасным, даже если в этом случае вы используете более безопасный вариант literal_eval
, который более ограничен, чем функция eval
.
Обычно то, что вы видите в файлах CSV, которые иметь много значений в одном столбце в том, что они будут использовать простой разделитель и заключать в кавычки поле.
Например:
ID,Country,Cities
1,Canada,"Toronto;Ottawa;Montreal"
Затем в python или любом другом языке, читать становится тривиально, не прибегая к eval
:
import csv
with open("data.csv") as fobj:
reader = csv.reader(fobj)
field_names = next(reader)
rows = []
for row in reader:
row[-1] = row[-1].split(";")
rows.append(row)
Проблемы с ast.literal_eval
Даже если функция ast.literal_eval
намного безопаснее, чем обычная eval
при вводе пользователем, он все еще может быть использован. В документации для literal_eval
есть это предупреждение:
Предупреждение: Возможно обработать sh интерпретатор Python с достаточно большим / сложная строка из-за ограничений глубины стека в компиляторе Python AST.
Демонстрацию этого можно найти здесь :
>>> import ast
>>> ast.literal_eval("()" * 10 ** 6)
[1] 48513 segmentation fault python
Я определенно не эксперт, но дать пользователю возможность взломать sh программу и потенциально использовать некоторую неясную уязвимость памяти - это плохо, и в этом случае можно избежать.
Если причина, по которой вы хотите использовать literal_eval
- для правильного набора текста, и вы уверены, что входные данные надежны на 100%, тогда я думаю, что это нормально. Но вы всегда можете обернуть функцию для выполнения некоторых проверок работоспособности:
def sanely_eval(value: str, max_size: int = 100_000) -> object:
if len(value) > max_size:
raise ValueError(f"len(value) is greater than the max_size={max_size!r}")
return ast.literal_eval(value)
Но, в зависимости от того, как вы создаете и используете файлы CSV, это может сделать данные менее переносимыми, поскольку это python -specifi c формат.