Как преобразовать сложные списки в строки и обратно в Python 3.7?

Я пытаюсь сохранить списки Python в файл и снова прочитать их при повторном запуске программы. Проблема в том, что мои списки сложны: т.е. разное количество кортежей внутри кортежей.

Лучшее, что я мог придумать, это сначала превратить мой список в строку (что работает), но я не могу придумать, как отменить изменения.

with open(filename, 'w') as f:
            f.write(str(objs))
            f.close()

Это работает, но как мне вернуть это в список?

Просто чтобы прояснить, каково мое определение сложного списка, вот пример:

[(((0.0, 0.0, 0.0), (1000.0, 0.0, 0.0), (0.0, 2.0, 0.0), (1000.0, 2.0, 
0.0), (0.0, 0.0, 1000.0), (1000.0, 0.0, 1000.0), (0.0, 2.0, 1000.0), 
(1000.0, 2.0, 1000.0)), ((0, 2, 3, 1), (4, 6, 7, 5), (1, 3, 7, 5), (4, 6, 
2, 0), (2, 6, 7, 3), (4, 0, 1, 5)), ((255, 0, 0), (255, 128, 0), (255, 255, 
0), (255, 255, 255), (0, 0, 255), (0, 255, 0)))]

person Grud Grud    schedule 19.02.2019    source источник
comment
Вы можете сохранить список в файле pickle или сохранить его как json (хотя это преобразует кортежи в списки).   -  person snakecharmerb    schedule 19.02.2019
comment
Лучшее, что я мог придумать, это превратить мой список в строку, изначально не делайте этого. Используйте поддерживаемый формат сериализации, например pickle для произвольных объектов, или даже просто json будет работать для простого списка.   -  person juanpa.arrivillaga    schedule 19.02.2019


Ответы (2)


Как уже упоминалось @snakecharmerb, вы можете использовать json или pickle. Вот пример:

Код:

my_list = [(((0.0, 0.0, 0.0), (1000.0, 0.0, 0.0), (0.0, 2.0, 0.0), (1000.0, 2.0, 
0.0), (0.0, 0.0, 1000.0), (1000.0, 0.0, 1000.0), (0.0, 2.0, 1000.0), 
(1000.0, 2.0, 1000.0)), ((0, 2, 3, 1), (4, 6, 7, 5), (1, 3, 7, 5), (4, 6, 
2, 0), (2, 6, 7, 3), (4, 0, 1, 5)), ((255, 0, 0), (255, 128, 0), (255, 255, 
0), (255, 255, 255), (0, 0, 255), (0, 255, 0)))]

import json

with open('my_list.json', 'w') as f:
    json.dump(my_list, f)

with open('my_list.json','r') as f:
    loaded_list = json.load(f)

print('Using json:')
print(loaded_list)

import pickle

with open('my_list.pkl', 'wb') as f:
    pickle.dump(my_list, f)

with open('my_list.pkl', 'rb') as f:
    loaded_list = pickle.load(f)

print('Using pickle:')
print(loaded_list)

Выход:

Using json:
[[[[0.0, 0.0, 0.0], [1000.0, 0.0, 0.0], [0.0, 2.0, 0.0], [1000.0, 2.0, 0.0], [0.0, 0.0, 1000.0], [1000.0, 0.0, 1000.0], [0.0, 2.0, 1000.0], [1000.0, 2.0, 1000.0]], [[0, 2, 3, 1], [4, 6, 7, 5], [1, 3, 7, 5], [4, 6, 2, 0], [2, 6, 7, 3], [4, 0, 1, 5]], [[255, 0, 0], [255, 128, 0], [255, 255, 0], [255, 255, 255], [0, 0, 255], [0, 255, 0]]]]

Using pickle:
[(((0.0, 0.0, 0.0), (1000.0, 0.0, 0.0), (0.0, 2.0, 0.0), (1000.0, 2.0, 0.0), (0.0, 0.0, 1000.0), (1000.0, 0.0, 1000.0), (0.0, 2.0, 1000.0), (1000.0, 2.0, 1000.0)), ((0, 2, 3, 1), (4, 6, 7, 5), (1, 3, 7, 5), (4, 6, 2, 0), (2, 6, 7, 3), (4, 0, 1, 5)), ((255, 0, 0), (255, 128, 0), (255, 255, 0), (255, 255, 255), (0, 0, 255), (0, 255, 0)))]

Как видите, json преобразует кортежи в списки.

person trsvchn    schedule 19.02.2019
comment
Да, это в точку. Таким образом, вместо первоначального преобразования списка в строку и записи в файл вы можете сохранить его в файле рассола. fileName = my_list fileObject = open(fileName,'wb') pickle.dump(my_list,fileObject) fileObject.close() - person Pallavi Roy; 19.02.2019
comment
Вы можете использовать cpickle вместо pickle, cpickle оптимизирован и намного быстрее, чем pickle, особенно если размер данных велик. приведенный выше код можно изменить, например, импортировать cpickle как pickle - person Ravishankar Sivasubramaniam; 10.04.2019

Функция str преобразует ваш сложный список/вложенные списки и кортеж в строку. Кроме того, eval преобразует любую строку в фактический фрагмент кода.

Однако, как упомянул Тарас Савчин, eval может привести к SQL-инъекциям и многому другому. Поэтому вместо этого используйте ast.literal_eval

Следовательно:

>>>import ast

>>> mylist = [(((0.0, 0.0, 0.0), (1000.0, 0.0, 0.0), (0.0, 2.0, 0.0), (1000.0, 2.0, 0.0), (0.0, 0.0, 1000.0), (1000.0, 0.0, 1000.0), (0.0, 2.0, 1000.0), (1000.0, 2.0, 1000.0)), ((0, 2, 3, 1), (4, 6, 7, 5), (1, 3, 7, 5), (4, 6, 2, 0), (2, 6, 7, 3), (4, 0, 1, 5)), ((255, 0, 0), (255, 128, 0), (255, 255, 0), (255, 255, 255), (0, 0, 255), (0, 255, 0)))]

>>> mylist
[(((0.0, 0.0, 0.0), (1000.0, 0.0, 0.0), (0.0, 2.0, 0.0), (1000.0, 2.0, 0.0), (0.0, 0.0, 1000.0), (1000.0, 0.0, 1000.0), (0.0, 2.0, 1000.0), (1000.0, 2.0, 1000.0)), ((0, 2, 3, 1), (4, 6, 7, 5), (1, 3, 7, 5), (4, 6, 2, 0), (2, 6, 7, 3), (4, 0, 1, 5)), ((255, 0, 0), (255, 128, 0), (255, 255, 0), (255, 255, 255), (0, 0, 255), (0, 255, 0)))]

>>> mystring = str(mylist)

>>> print(mystring)
'[(((0.0, 0.0, 0.0), (1000.0, 0.0, 0.0), (0.0, 2.0, 0.0), (1000.0, 2.0, 0.0), (0.0, 0.0, 1000.0), (1000.0, 0.0, 1000.0), (0.0, 2.0, 1000.0), (1000.0, 2.0, 1000.0)), ((0, 2, 3, 1), (4, 6, 7, 5), (1, 3, 7, 5), (4, 6, 2, 0), (2, 6, 7, 3), (4, 0, 1, 5)), ((255, 0, 0), (255, 128, 0), (255, 255, 0), (255, 255, 255), (0, 0, 255), (0, 255, 0)))]'

>>> type(mystring)
<class 'str'>

>>> print(ast.literal_eval(mystring))
[(((0.0, 0.0, 0.0), (1000.0, 0.0, 0.0), (0.0, 2.0, 0.0), (1000.0, 2.0, 0.0), (0.0, 0.0, 1000.0), (1000.0, 0.0, 1000.0), (0.0, 2.0, 1000.0), (1000.0, 2.0, 1000.0)), ((0, 2, 3, 1), (4, 6, 7, 5), (1, 3, 7, 5), (4, 6, 2, 0), (2, 6, 7, 3), (4, 0, 1, 5)), ((255, 0, 0), (255, 128, 0), (255, 255, 0), (255, 255, 255), (0, 0, 255), (0, 255, 0)))]

>>> type(ast.literal_eval(mystring))
<class 'list'>

Надеюсь, это решит вашу проблему. Вы можете прокомментировать ответ, чтобы задать любые дополнительные вопросы

person Varun Chhangani    schedule 19.02.2019
comment
Использование eval — плохая практика. stackoverflow.com/questions/1832940 / - person trsvchn; 19.02.2019