Как сохранить и восстановить несколько переменных в 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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.