Jak mogę użyć marynaty, aby zapisać dykt?


370

Przejrzałem informacje podane w dokumentach Pythona , ale wciąż jestem trochę zdezorientowany. Czy ktoś mógłby napisać przykładowy kod, który napisałby nowy plik, a następnie użyć zalewy, aby wrzucić do niego słownik?


5
Przeczytaj to: doughellmann.com/PyMOTW/pickle i wróć, gdy potrzebujesz konkretnego pytania
— pyfunc

2
-1 Zobacz poprzednie komentarze. Spróbuj. Następnie, jeśli to nie zadziała (nie zawsze), można sformułować ukierunkowane pytanie (wraz z hipotezą lub dwiema, które można przetestować i „zapytać”, być może przed zadaniem pytania innym osobom). Np. Czy wystąpił błąd składniowy? Wyjątek? Czy wartości wróciły zniekształcone?

1
Próbowałem to wykorzystać, aby zapisać informacje o grze. Wykorzystałem powyższe informacje i mój kod wygląda następująco:
— Chachmu

name = raw_input ('nazwa pliku wejściowego:') tf = open (name + '. pkl', 'wb') pickle.dump (total, tf) tf.close ()
— Chachmu

2
Powinieneś zadać nowe pytanie o tym, jak wytrawiać obiekty powierzchniowe
— John La Rooy,

Odpowiedzi:


727

Spróbuj tego:

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: Dlaczego usunąłeś pickle.HIGHEST_PROTOCOL?
— Blender

37
@Blender: nieistotne i niepotrzebnie skomplikowane dla tego poziomu pytania - przeciętny użytkownik będzie w porządku z ustawieniami domyślnymi.
— houbysoft,

28
@houbysoft: Prawda dla użytkowników Python 3, ale w Python 2 użycie domyślnego protokołu (0) jest nie tylko niesamowicie nieefektywne w czasie i przestrzeni, ale nie jest w stanie poradzić sobie z wieloma rzeczami, które protokół 2+ obsługuje dobrze (np. nowy klasy, które używają __slots__). Nie twierdzę, że zawsze powinieneś używać HIGHEST_PROTOCOL, ale upewnienie się, że nie używasz protokołu 0 lub 1, jest w rzeczywistości raczej ważne.
— ShadowRanger

11
Co pickle.HIGHEST_PROTOCOLwłaściwie robi?
— BallpointBen

7
@BallpointBen: wybiera najwyższą wersję protokołu obsługiwaną przez twoją wersję Pythona: 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)

Zaletą HIGHEST_PROTOCOLjest to, że pliki stają się mniejsze. To sprawia, że ​​odznaczanie czasami jest znacznie szybsze.

Ważna uwaga : Maksymalny rozmiar pliku marynowanego wynosi około 2 GB.

Alternatywny sposób

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

Alternatywne formaty

W przypadku aplikacji ważne mogą być:

  • Wsparcie z innych języków programowania
  • Wydajność czytania / pisania
  • Kompaktowość (rozmiar pliku)

Zobacz także: Porównanie formatów serializacji danych

Jeśli szukasz sposobu na utworzenie plików konfiguracyjnych, możesz przeczytać mój krótki artykuł Pliki konfiguracyjne w Pythonie


1
Myślę, że limit 2 GB został usunięty przy protokole = 4 i wyższym.
— 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
czy konieczne jest użycie close () po open ()?
— PlsWork

1
Tak, ogólnie. Jednak w CPython (domyślny python, który prawdopodobnie masz) plik jest automatycznie zamykany za każdym razem, gdy obiekt pliku wygasa (gdy nic do niego nie odnosi). W tym przypadku, ponieważ nic nie odwołuje się do obiektu pliku po zwróceniu przez open (), zostanie on zamknięty, gdy tylko wróci ładowanie. Nie jest to uważane za dobrą praktykę i spowoduje problemy w innych systemach
— Ankur S

14

Ogólnie, wytrawianie dictnie powiedzie się, chyba że masz w nim tylko proste obiekty, takie jak łańcuchy i liczby całkowite.

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
>>> 

Nawet bardzo proste dictczęsto się nie powiedzie. To zależy tylko od zawartości.

>>> 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>

Jeśli jednak używasz lepszego serializatora, takiego jak dilllub cloudpickle, większość słowników można marynować:

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

Lub jeśli chcesz zapisać swój dictplik ...

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

Ten ostatni przykład jest identyczny z innymi dobrymi odpowiedziami zamieszczonymi tutaj (które oprócz zaniedbania możliwości wyboru zawartości dictsą dobre).


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

zwykle lepiej jest użyć implementacji 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

Jeśli chcesz zapisać nagranie w jednym pliku, użyj pickletego

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)

Jeśli chcesz zapisać i przywrócić wiele słowników w wielu plikach do buforowania i przechowywać bardziej złożone dane, skorzystaj z pamięci podręcznej . Robi wszystkie inne rzeczy, których potrzebujeszpickle

from anycache import anycache

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

Anycache przechowuje różne myfuncwyniki w zależności od argumentów w różnych plikach cachediri ładuje je ponownie.

Więcej informacji można znaleźć w dokumentacji .


6

Prosty sposób na zrzucenie danych Pythona (np. Słownika) do pliku marynowanego.

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

Wytrawianie było mylące (prawdopodobnie dlatego, że jestem gruby). Przekonałem się, że to działa:

myDictionaryString=str(myDictionary)

Które możesz następnie zapisać do pliku tekstowego. Zrezygnowałem z prób używania marynaty, ponieważ otrzymywałem błędy mówiące, żebym zapisywał liczby całkowite w pliku .dat. Przepraszam, że nie użyłem marynaty.


1
-1: Powinien zapisać go takim, jaki jest (tj. Obiekt python), abyśmy mogli go później odczytać bez godzin oczekiwania na ponowne uruchomienie. Pickle pozwala nam przechowywać obiekt Pythona do późniejszego przeczytania.
— Catbuilts,

To stara odpowiedź wracająca do kolejki o niskiej jakości. Nie jest to złe rozwiązanie, ponieważ prawdopodobnie działa w przypadku bardzo prostych słowników, ale rozsądne jest, dictaby zawierała większą głębokość obiektów (które można wydrukować tylko przez nazwa) i / lub obiektów bez żadnej lub pełnej reprezentacji ciągu.
— ti7

1
Aby dodać do punktu @ ti7, niezależnie od technicznej wartości odpowiedzi, ten post nie jest VLQ. Jeśli ktoś uważa, że ​​ta odpowiedź jest niedokładna, powinien głosować i / lub komentować, wyjaśniając dlaczego, a nie oznaczać go jako VLQ.
— EJoshuaS - Przywróć Monikę
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.