Как сохранить и восстановить несколько переменных в Python?

106

Мне нужно сохранить около дюжины объектов в файл, а потом восстановить их. Я пытался использовать цикл for с рассолом и полкой, но это не сработало.

Редактировать.
Все объекты, которые я пытался сохранить, находились в одном классе (я должен был упомянуть об этом раньше), и я не понимал, что могу просто сохранить весь класс следующим образом:

import pickle
def saveLoad(opt):
    global calc
    if opt == "save":
        f = file(filename, 'wb')
        pickle.dump(calc, f, 2)
        f.close
        print 'data saved'
    elif opt == "load":
        f = file(filename, 'rb')
        calc = pickle.load(f)
    else:
        print 'Invalid saveLoad option'
лунный огонь
источник
1
Вы говорите, что пробовали цикл for. Пожалуйста, опубликуйте этот код и объясните, почему «он не сработал» (то есть, что произошло и что вы хотели).
Blair
Если вы находитесь на окна, убедитесь , чтобы открыть файлы в двоичном режиме
Джон Ла Роой
@gnibbler: двоичный режим необходим только для протоколов, отличных от стандартных ( docs.python.org/library/pickle.html#usage ).
Eric O Lebigot

Ответы:

172

Если вам нужно сохранить несколько объектов, вы можете просто поместить их в один список или кортеж, например:

import pickle

# obj0, obj1, obj2 are created here...

# Saving the objects:
with open('objs.pkl', 'w') as f:  # Python 3: open(..., 'wb')
    pickle.dump([obj0, obj1, obj2], f)

# Getting back the objects:
with open('objs.pkl') as f:  # Python 3: open(..., 'rb')
    obj0, obj1, obj2 = pickle.load(f)

Если у вас много данных, вы можете уменьшить размер файла, перейдя protocol=-1к dump(); pickleзатем будет использовать наилучший доступный протокол вместо исторического (и более обратно совместимого) протокола по умолчанию. В этом случае файл необходимо открыть в двоичном режиме ( wbи rb, соответственно).

Двоичный режим также следует использовать с Python 3, поскольку его протокол по умолчанию производит двоичные (т.е. нетекстовые) данные (режим записи и режим 'wb'чтения 'rb').

Эрик О Лебигот
источник
12
В Python 3.5 мне приходилось открывать файл в «байтовом» режиме, например with open('objs.pickle', 'wb') as f:(обратите внимание на wb).
kbrose
Привет @ Эрик, зачем with open('objs.pkl') as f:просто сравнивать obj1, obj2 = pickle.load(open("objs.pkl","rb"))? Есть ли разница между этими двумя?
balandongiv
Во второй форме вы не закрываете файл. Это не считается хорошей практикой, поскольку количество файлов, которые можно открывать параллельно, обычно сильно ограничено операционными системами (попробуйте цикл, который открывает файлы, не закрывая их!). Тем не менее, на практике не закрытие файла часто срабатывает, когда вы не открываете много файлов.
Эрик О Лебигот,
51

Есть встроенная библиотека под названием pickle. Используя pickleвы можете выгружать объекты в файл и загружать их позже.

import pickle

f = open('store.pckl', 'wb')
pickle.dump(obj, f)
f.close()

f = open('store.pckl', 'rb')
obj = pickle.load(f)
f.close()
Йосси
источник
1
Я Python 3.4 использую: f = open('store.pckl', 'wb')чтобы открыть файл для записи. Обратитесь к stackoverflow.com/questions/13906623/… И используйте `f = open ('store.pckl', 'rb'), чтобы открыть файл для чтения. См. Stackoverflow.com/questions/7031699/… .
user3731622
это характерно для 3.4+? Я чуть не проголосовал за ответ, потому что он генерирует ошибки, когда вы не используете 'b'.
Wilmer E. Henao
12

Стоит посмотреть на полки и модули рассола . Если вам нужно хранить много данных, может быть лучше использовать базу данных

Джон Ла Рой
источник
Я хочу сохранить один объект, который входит в облачный сервер, чтобы обработать, если я вхожу в систему несколько раз с течением времени, сервер отклоняет мой запрос. Может ли сбрасывание объекта в файл с помощью модуля pickle иметь какие-либо проблемы с безопасностью? , например, если кто-то получит мой сброшенный объект, он сможет войти в мое облачное хранилище без пароля.
alper
6

Другой подход к сохранению нескольких переменных в файл рассола:

import pickle

a = 3; b = [11,223,435];
pickle.dump([a,b], open("trial.p", "wb"))

c,d = pickle.load(open("trial.p","rb"))

print(c,d) ## To verify
Гурупрасад Рагхаван
источник
4

Вы можете использовать klepto, который обеспечивает постоянное кэширование в памяти, на диске или в базе данных.

dude@hilbert>$ python
Python 2.7.6 (default, Nov 12 2013, 13:26:39) 
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from klepto.archives import file_archive
>>> db = file_archive('foo.txt')
>>> db['1'] = 1
>>> db['max'] = max
>>> squared = lambda x: x**2
>>> db['squared'] = squared
>>> def add(x,y):
...   return x+y
... 
>>> db['add'] = add
>>> class Foo(object):
...   y = 1
...   def bar(self, x):
...     return self.y + x
... 
>>> db['Foo'] = Foo
>>> f = Foo()
>>> db['f'] = f  
>>> db.dump()
>>> 

Затем после перезапуска интерпретатора ...

dude@hilbert>$ python
Python 2.7.6 (default, Nov 12 2013, 13:26:39) 
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from klepto.archives import file_archive
>>> db = file_archive('foo.txt')
>>> db
file_archive('foo.txt', {}, cached=True)
>>> db.load()
>>> db
file_archive('foo.txt', {'1': 1, 'add': <function add at 0x10610a0c8>, 'f': <__main__.Foo object at 0x10510ced0>, 'max': <built-in function max>, 'Foo': <class '__main__.Foo'>, 'squared': <function <lambda> at 0x10610a1b8>}, cached=True)
>>> db['add'](2,3)
5
>>> db['squared'](3)
9
>>> db['f'].bar(4)
5
>>> 

Получите код здесь: https://github.com/uqfoundation

Майк МакКернс
источник
7
OP не просил встроенного.
Майк МакКернс,
4

Следующий подход кажется простым и может использоваться с переменными разного размера:

import hickle as hkl
# write variables to filename [a,b,c can be of any size]
hkl.dump([a,b,c], filename)

# load variables from filename
a,b,c = hkl.load(filename)
дьявол в деталях
источник
hicklepackage более надежен (меньше подвержен ошибкам) ​​и даже проще (меньше кода), чем pickle.
user2340939