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?

Chachmu
źródło
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
Mikser
źródło
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

Martin Thoma
źródło
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"}
użytkownik3465692
źródło
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).

Mike McKerns
źródło
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.
John La Rooy
źródło
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 .

c0fec0de
źródło
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'))
Prashanth Muthurajaiah
źródło
3
import pickle

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

filename = "/foldername/filestore"

fileobj = open(filename, 'wb')

pickle.dump(dictobj, fileobj)

fileobj.close()
Rahul Nair
źródło
-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.

Pedro Rhian
źródło
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ę