Як я можу використовувати соління для збереження диктату?


370

Я переглянув інформацію, яку надають документи Python , але я все ще трохи розгублений. Чи може хтось розмістити зразок коду, який би написав новий файл, а потім за допомогою маринаду скинути до нього словник?


5
Прочитайте це: doughellmann.com/PyMOTW/pickle і повертайтеся, коли вам потрібно конкретне запитання
pyfunc

2
-1 Дивіться попередні коментарі. Спробуй це. Тоді, якщо це не спрацювало (це не завжди), можна сформулювати спрямоване запитання (разом із гіпотезою чи двома, які можна перевірити та "запитувати на запит", можливо, перш ніж задавати питання іншим людям). Наприклад, чи була синтаксична помилка? Виняток? Чи повернулися цінні показники?

1
Я намагався використати це, щоб зберегти інформацію від піґами. Я використав інформацію вище, і мій код виглядає приблизно так:
Chachmu

name = raw_input ('ім'я вхідного файлу:') tf = відкрито (ім'я + '. pkl', 'wb') pickle.dump (всього, tf) tf.close ()
Chachmu

2
Вам слід задати нове запитання про те, як маринувати поверхневі об’єкти
Джон Ла Рой

Відповіді:


727

Спробуйте це:

import pickle

a = {'hello': 'world'}

with open('filename.pickle', 'wb') as handle:
    pickle.dump(a, handle, protocol=pickle.HIGHEST_PROTOCOL)

with open('filename.pickle', 'rb') as handle:
    b = pickle.load(handle)

print a == b

4
@houbysoft: Чому ви видалили pickle.HIGHEST_PROTOCOL?
Блендер

37
@Blender: неактуально і непотрібно ускладнювати цей рівень запитань - середньому користувачеві буде просто добре за замовчуванням.
houbysoft

28
@houbysoft: Правда для користувачів Python 3, але для Python 2 використання протоколу за замовчуванням (0) не лише неймовірно неефективне у часі та просторі, але й не може насправді обробляти багато речей, якими протокол 2+ обробляє просто чудово (наприклад, новий -класові класи, які використовують __slots__). Я не кажу, що ви завжди повинні використовувати HIGHEST_PROTOCOL, але гарантувати, що ви не використовуєте протокол 0 або 1, насправді досить важливо.
ShadowRanger

11
Що pickle.HIGHEST_PROTOCOLнасправді робить?
BallpointBen

7
@BallpointBen: Він вибирає найвищу версію протоколу, яку підтримує ваша версія Python: docs.python.org/3/library/pickle.html#data-stream-format
Blender

92
import pickle

your_data = {'foo': 'bar'}

# Store data (serialize)
with open('filename.pickle', 'wb') as handle:
    pickle.dump(your_data, handle, protocol=pickle.HIGHEST_PROTOCOL)

# Load data (deserialize)
with open('filename.pickle', 'rb') as handle:
    unserialized_data = pickle.load(handle)

print(your_data == unserialized_data)

Перевагою HIGHEST_PROTOCOLє те, що файлів стає менше. Це робить вилучення іноді набагато швидшим.

Важливе повідомлення : Максимальний розмір файлу соління - близько 2 ГБ.

Альтернативний спосіб

import mpu
your_data = {'foo': 'bar'}
mpu.io.write('filename.pickle', data)
unserialized_data = mpu.io.read('filename.pickle')

Альтернативні формати

Для вашої заявки може бути важливим наступне:

  • Підтримка іншими мовами програмування
  • Виконання читання / письма
  • Компактність (розмір файлу)

Дивіться також: Порівняння форматів серіалізації даних

Якщо ви шукаєте спосіб створення файлів конфігурації, ви можете прочитати мою коротку статтю Конфігураційні файли в Python


1
Я думаю, що ліміт 2 Гб було знято з протоколом = 4 і вище.
ComputerScientist

28
# Save a dictionary into a pickle file.
import pickle

favorite_color = {"lion": "yellow", "kitty": "red"}  # create a dictionary
pickle.dump(favorite_color, open("save.p", "wb"))  # save it into a file named save.p

# -------------------------------------------------------------
# Load the dictionary back from the pickle file.
import pickle

favorite_color = pickle.load(open("save.p", "rb"))
# favorite_color is now {"lion": "yellow", "kitty": "red"}

1
чи потрібно використовувати close () після відкритого ()?
PlsWork

1
Так, загалом. Однак у CPython (python за замовчуванням, який у вас, мабуть), файл автоматично закривається щоразу, коли закінчується термін дії об'єкта файлу (коли на нього нічого не відноситься). У цьому випадку, оскільки нічого не посилається на файл-об’єкт після повернення open (), він буде закритий, як тільки завантаження повернеться. Це не вважається належною практикою і спричинить проблеми в інших системах
Ankur S

14

Загалом, вибирати атрибут dictне вдасться, якщо у вас є лише прості об'єкти, такі як рядки та цілі числа.

Python 2.7.9 (default, Dec 11 2014, 01:21:43) 
[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 numpy import *
>>> type(globals())     
<type 'dict'>
>>> import pickle
>>> pik = pickle.dumps(globals())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 1374, in dumps
    Pickler(file, protocol).dump(obj)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 224, in dump
    self.save(obj)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 649, in save_dict
    self._batch_setitems(obj.iteritems())
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 663, in _batch_setitems
    save(v)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 306, in save
    rv = reduce(self.proto)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/copy_reg.py", line 70, in _reduce_ex
    raise TypeError, "can't pickle %s objects" % base.__name__
TypeError: can't pickle module objects
>>> 

Навіть по- справжньому простий dictчасто вийде з ладу. Це просто залежить від змісту.

>>> d = {'x': lambda x:x}
>>> pik = pickle.dumps(d)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 1374, in dumps
    Pickler(file, protocol).dump(obj)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 224, in dump
    self.save(obj)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 649, in save_dict
    self._batch_setitems(obj.iteritems())
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 663, in _batch_setitems
    save(v)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 748, in save_global
    (obj, module, name))
pickle.PicklingError: Can't pickle <function <lambda> at 0x102178668>: it's not found as __main__.<lambda>

Однак якщо ви використовуєте кращий серіалізатор на кшталт dillабо cloudpickle, то більшість словників можна маринувати:

>>> import dill
>>> pik = dill.dumps(d)

Або якщо ви хочете зберегти свій dictфайл у файлі ...

>>> with open('save.pik', 'w') as f:
...   dill.dump(globals(), f)
... 

Останній приклад ідентичний будь-якому з інших хороших відповідей, розміщених тут (які окрім того, що нехтувати добірністю вмісту dictє хорошим).


9
>>> import pickle
>>> with open("/tmp/picklefile", "wb") as f:
...     pickle.dump({}, f)
... 

зазвичай краще використовувати реалізацію cPickle

>>> import cPickle as pickle
>>> help(pickle.dump)
Help on built-in function dump in module cPickle:

dump(...)
    dump(obj, file, protocol=0) -- Write an object in pickle format to the given file.

    See the Pickler docstring for the meaning of optional argument proto.

6

Якщо ви просто хочете зберігати дикт в одному файлі, використовуйте pickleтак

import pickle

a = {'hello': 'world'}

with open('filename.pickle', 'wb') as handle:
    pickle.dump(a, handle)

with open('filename.pickle', 'rb') as handle:
    b = pickle.load(handle)

Якщо ви хочете зберегти та відновити кілька словників у кількох файлах для кешування та зберігання складніших даних, використовуйте будь-який кеш . Це все, що вам потрібно навколоpickle

from anycache import anycache

@anycache(cachedir='path/to/files')
def myfunc(hello):
    return {'hello', hello}

Anycache зберігає різні myfuncрезультати залежно від аргументів для різних файлів cachedirі перезавантажує їх.

Детальнішу інформацію див. У документації .


6

Простий спосіб скинути дані Python (наприклад, словник) у файл зібрання.

import pickle

your_dictionary = {}

pickle.dump(your_dictionary, open('pickle_file_name.p', 'wb'))

3
import pickle

dictobj = {'Jack' : 123, 'John' : 456}

filename = "/foldername/filestore"

fileobj = open(filename, 'wb')

pickle.dump(dictobj, fileobj)

fileobj.close()

-8

Соління я виявив заплутаним (можливо, тому, що я товстий). Я виявив, що це працює, хоча:

myDictionaryString=str(myDictionary)

Який ви можете потім записати у текстовий файл. Я відмовився від спроби використовувати соління, коли я отримував помилки, які говорили мені написати цілі числа у файл .dat. Прошу вибачення за те, що не використовую соління.


1
-1: Потрібно зберегти його таким, яким він є (тобто об'єктом python), щоб ми могли прочитати його пізніше, не чекаючи годин, щоб запустити його знову. Pickle дозволяє нам зберігати пітонний об’єкт для читання пізніше.
Catbuilts

Це стара відповідь, що повертається в черзі повідомлень про низьку якість. Це не погане рішення в тому, що воно, ймовірно, працює для дуже простих словників, але це дуже розумно, dictщоб містити подальшу глибину об'єктів (які можуть бути надруковані просто ім'я) та / або об'єкти без будь-якого або повного представлення рядків.
ti7

1
Щоб додати пункт @ ti7, незалежно від технічних достоїнств відповіді, ця публікація не є VLQ. Якщо хтось вважає, що ця відповідь неточна, він повинен спровокувати та / або прокоментувати пояснення чому, а не позначити її як VLQ.
EJoshuaS
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.