ฉันจะใช้ pickle เพื่อบันทึก dict ได้อย่างไร?


370

ฉันได้ตรวจสอบข้อมูลที่เอกสารของ Pythonให้มาแล้ว แต่ฉันยังสับสนอยู่เล็กน้อย มีใครบางคนโพสต์โค้ดตัวอย่างที่จะเขียนไฟล์ใหม่จากนั้นใช้ pickle เพื่อถ่ายโอนพจนานุกรมลงไป


5
อ่านผ่านทางนี้: doughellmann.com/PyMOTW/pickleแล้วกลับมาใหม่เมื่อคุณต้องการคำถามที่เฉพาะเจาะจง
pyfunc

2
-1 ดูความคิดเห็นก่อนหน้า ลองมัน. จากนั้นหากไม่ได้ผล (อาจไม่เสมอไป) คำถามที่ถูกกำหนดจะถูกกำหนดขึ้น (รวมถึงสมมติฐานหรือสองข้อที่สามารถทดสอบได้และ "สอบถามเพื่อ" อาจเป็นไปได้ก่อนถามคำถามกับผู้อื่น) เช่นมีข้อผิดพลาดทางไวยากรณ์หรือไม่ ข้อยกเว้น? ค่าเหล่านั้นกลับมาบิดเบือนหรือไม่?

1
ฉันพยายามใช้สิ่งนี้เพื่อบันทึกข้อมูลจาก pygame ฉันได้ใช้ข้อมูลข้างต้นและรหัสของฉันมีลักษณะเช่นนี้:
Chachmu

name = raw_input ('ชื่อไฟล์อินพุต:') tf = open (ชื่อ + '. pkl', 'wb') pickle.dump (ทั้งหมด, tf) tf.close ()
Chachmu

2
คุณควรถามคำถามใหม่เกี่ยวกับวิธีดองวัตถุพื้นผิว
John La Rooy

คำตอบ:


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

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คือไฟล์จะเล็กลง ทำให้บางครั้งการถอนออกเร็วขึ้นมาก

ประกาศสำคัญ : ขนาดไฟล์สูงสุดของดองคือประมาณ 2GB

ทางเลือกอื่น

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

รูปแบบอื่น ๆ

สำหรับแอปพลิเคชันของคุณข้อมูลต่อไปนี้อาจสำคัญ:

  • สนับสนุนโดยภาษาโปรแกรมอื่น ๆ
  • การอ่าน / เขียนประสิทธิภาพ
  • ความกะทัดรัด (ขนาดไฟล์)

ดูเพิ่มเติม: การเปรียบเทียบรูปแบบการจัดลำดับข้อมูล

ในกรณีที่คุณกำลังมองหาวิธีสร้างไฟล์การกำหนดค่าคุณอาจต้องการอ่านบทความสั้น ๆ ของฉันไฟล์การตั้งค่าใน Python


1
ฉันคิดว่าขีด จำกัด 2GB ถูกลบโดยใช้โปรโตคอล = 4 ขึ้นไป
วิทยาศาสตร์คอมพิวเตอร์

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
จำเป็นต้องใช้การปิด () หลังจากการเปิด () หรือไม่
PlsWork

1
ใช่โดยทั่วไป อย่างไรก็ตามใน CPython (ไพ ธ อนเริ่มต้นที่คุณอาจมี) ไฟล์จะถูกปิดโดยอัตโนมัติเมื่อใดก็ตามที่วัตถุไฟล์หมดอายุ (เมื่อไม่มีสิ่งใดอ้างถึง) ในกรณีนี้เนื่องจากไม่มีสิ่งใดอ้างถึงอ็อบเจ็กต์ไฟล์หลังจากส่งคืนโดย 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>

แต่ถ้าคุณใช้ serializer ดีขึ้นเหมือน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

หากคุณต้องการเก็บ dict ในไฟล์เดียวให้ใช้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)

หากคุณต้องการที่จะบันทึกและเรียกคืนพจนานุกรมหลายในหลายไฟล์สำหรับการแคชและจัดเก็บข้อมูลที่ซับซ้อนมากขึ้นการใช้anycache มันทำทุกอย่างที่คุณต้องการ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'))


-8

ฉันพบความสับสนในการดอง (อาจเป็นเพราะฉันหนา) ฉันพบว่ามันใช้งานได้ดี:

myDictionaryString=str(myDictionary)

ซึ่งคุณสามารถเขียนไปยังไฟล์ข้อความ ฉันเลิกพยายามใช้ดองเพราะฉันได้รับข้อผิดพลาดบอกให้ฉันเขียนจำนวนเต็มไปยังไฟล์. dat ฉันขอโทษที่ไม่ได้ใช้ดอง


1
-1: ควรบันทึกตามที่เป็น (เช่นวัตถุหลาม) เพื่อให้เราสามารถอ่านได้ในภายหลังโดยไม่ต้องรอชั่วโมงเพื่อเรียกใช้อีกครั้ง Pickle ช่วยให้เราสามารถเก็บวัตถุหลามเพื่ออ่านในภายหลัง
Catbuilts

นี่คือคำตอบกลับมาอายุต่ำคุณภาพโพสต์คิว .. มันไม่ได้เป็นวิธีการแก้ปัญหาที่ไม่ดีในการที่จะมีโอกาสทำงานสำหรับพจนานุกรมง่ายมาก แต่มันเป็นที่เหมาะสมมากสำหรับdictที่จะมีความลึกของวัตถุ (ซึ่งอาจจะพิมพ์เพียงแค่ ชื่อ) และ / หรือวัตถุที่ไม่มีการแทนสตริงใด ๆ หรือสมบูรณ์
Ti7 7

1
หากต้องการเพิ่มจุดของ @ ti7 โดยไม่คำนึงถึงข้อดีทางเทคนิคของคำตอบโพสต์นี้ไม่ใช่ VLQ หากมีคนรู้สึกว่าคำตอบนี้ไม่ถูกต้องพวกเขาควรจะลงคะแนนและ / หรือแสดงความคิดเห็นอธิบายว่าทำไมไม่ตั้งค่าสถานะเป็น VLQ
EJoshuaS - Reinstate Monica
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.