Bagaimana saya bisa menggunakan acar untuk menyimpan dict?

370

Saya telah melihat informasi yang diberikan Python docs , tapi saya masih sedikit bingung. Bisakah seseorang memposting kode sampel yang akan menulis file baru kemudian menggunakan acar untuk membuang kamus ke dalamnya?

Chachmu
sumber
5
Baca ini: doughellmann.com/PyMOTW/pickle dan kembali ketika Anda membutuhkan pertanyaan khusus
pyfunc
2
-1 Lihat komentar sebelumnya. Cobalah. Kemudian, jika itu tidak berhasil (tidak akan selalu), pertanyaan terarah dapat dirumuskan (bersama dengan satu atau dua hipotesis yang dapat diuji, dan "dimintai pertanyaan", mungkin sebelum mengajukan pertanyaan kepada orang lain). Misalnya apakah ada kesalahan sintaksis? Pengecualian? Apakah nilai-nilai kembali kacau?
1
Saya telah mencoba menggunakan ini untuk menyimpan informasi dari pygame. Saya telah menggunakan informasi di atas dan kode saya terlihat seperti ini:
Chachmu
name = raw_input ('input file name:') tf = open (name + '. pkl', 'wb') pickle.dump (total, tf) tf.close ()
Chachmu
2
Anda harus mengajukan pertanyaan baru tentang cara membuat acar benda permukaan
John La Rooy

Jawaban:

728

Coba ini:

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
Blender
sumber
4
@houbysoft: Mengapa Anda menghapus pickle.HIGHEST_PROTOCOL?
Blender
37
@Blender: tidak relevan dan tidak perlu rumit untuk tingkat pertanyaan ini - rata-rata pengguna akan baik-baik saja dengan default.
houbysoft
28
@houbysoft: Benar untuk pengguna Python 3, tetapi pada Python 2, menggunakan protokol default (0) tidak hanya sangat tidak efisien pada waktu dan ruang, tetapi sebenarnya tidak dapat menangani banyak hal yang ditangani protokol 2+ dengan baik (misalnya baru kelas-gaya yang digunakan __slots__). Saya tidak mengatakan Anda harus selalu menggunakan HIGHEST_PROTOCOL, tetapi memastikan Anda tidak menggunakan protokol 0 atau 1 sebenarnya agak penting.
ShadowRanger
11
Apa yang pickle.HIGHEST_PROTOCOLsebenarnya dilakukan?
BallpointBen
7
@BallpointBen: Ini mengambil versi protokol tertinggi yang didukung oleh versi Python Anda: 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)

Keuntungannya HIGHEST_PROTOCOLadalah file menjadi lebih kecil. Ini membuat pembongkaran terkadang jauh lebih cepat.

Pemberitahuan penting : Ukuran file acar maksimum adalah sekitar 2GB.

Cara alternatif

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

Format Alternatif

Untuk aplikasi Anda, berikut ini mungkin penting:

  • Dukungan oleh bahasa pemrograman lain
  • Kinerja membaca / menulis
  • Kekompakan (ukuran file)

Lihat juga: Perbandingan format serialisasi data

Jika Anda mencari cara untuk membuat file konfigurasi, Anda mungkin ingin membaca artikel pendek saya File konfigurasi dalam Python

Martin Thoma
sumber
1
Saya pikir batas 2GB telah dihapus dengan protokol = 4 dan lebih tinggi.
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"}
pengguna3465692
sumber
1
apakah perlu menggunakan close () setelah open ()?
PlsWork
1
Ya, secara umum. Namun dalam CPython (Python default yang mungkin Anda miliki) file secara otomatis ditutup setiap kali objek file berakhir (ketika tidak ada yang merujuk padanya). Dalam hal ini karena tidak ada yang merujuk ke objek file setelah dikembalikan oleh open (), itu akan ditutup segera setelah memuat kembali. Ini tidak dianggap praktik yang baik dan akan menyebabkan masalah pada sistem lain
Ankur S
14

Secara umum, pengawetan a dictakan gagal kecuali Anda hanya memiliki objek sederhana di dalamnya, seperti string dan integer.

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

Bahkan yang sangat sederhana dictakan sering gagal. Itu tergantung isinya saja.

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

Namun, jika Anda menggunakan serializer yang lebih baik seperti dillatau cloudpickle, maka sebagian besar kamus dapat diacak:

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

Atau jika Anda ingin menyimpannya dictke file ...

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

Contoh terakhir identik dengan jawaban baik lainnya yang diposting di sini (yang selain mengabaikan picklability dari konten dictyang baik).

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

biasanya lebih baik menggunakan implementasi 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
sumber
6

Jika Anda hanya ingin menyimpan dikt dalam satu file, gunakan pickleseperti itu

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)

Jika Anda ingin menyimpan dan mengembalikan beberapa kamus dalam banyak file untuk menyimpan dan menyimpan data yang lebih kompleks, gunakan anycache . Itu semua hal lain yang Anda butuhkanpickle

from anycache import anycache

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

Anycache menyimpan myfunchasil yang berbeda tergantung pada argumen untuk file yang berbeda cachedirdan memuatnya kembali.

Lihat dokumentasi untuk rincian lebih lanjut.

c0fec0de
sumber
6

Cara sederhana untuk membuang data Python (misalnya kamus) ke file acar.

import pickle

your_dictionary = {}

pickle.dump(your_dictionary, open('pickle_file_name.p', 'wb'))
Prashanth Muthurajaiah
sumber
3
import pickle

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

filename = "/foldername/filestore"

fileobj = open(filename, 'wb')

pickle.dump(dictobj, fileobj)

fileobj.close()
Rahul Nair
sumber
-8

Saya merasa acar membingungkan (mungkin karena saya kental). Saya menemukan bahwa ini bekerja, namun:

myDictionaryString=str(myDictionary)

Yang kemudian dapat Anda tulis ke file teks. Saya menyerah mencoba menggunakan acar karena saya mendapatkan kesalahan mengatakan kepada saya untuk menulis bilangan bulat ke file dat. Saya minta maaf karena tidak menggunakan acar.

Pedro Rhian
sumber
1
-1: Seharusnya menyimpannya apa adanya (yaitu, objek python) sehingga kita dapat membacanya nanti tanpa jam menunggu untuk menjalankannya lagi. Acar memungkinkan kita untuk menyimpan objek python untuk dibaca nanti.
Catbuilts
Ini adalah jawaban lama yang kembali dalam antrian Kiriman Rendah Kualitas .. Ini bukan solusi yang buruk karena kemungkinan akan berfungsi untuk kamus yang sangat sederhana, tetapi sangat masuk akal jika dictmengandung kedalaman objek lebih lanjut (yang dapat dicetak hanya dengan nama) dan / atau objek tanpa representasi string lengkap atau apa pun.
ti7
1
Untuk menambah poin @ ti7, terlepas dari kemampuan teknis jawabannya, postingan ini bukan VLQ. Jika seseorang merasa bahwa jawaban ini tidak akurat, mereka harus memilih dan / atau berkomentar menjelaskan alasannya, bukan menandai sebagai VLQ.
EJoshuaS