【问题标题】:How can I use pickle to save a dict (or any other Python object)?如何使用 pickle 保存字典?
【发布时间】:2012-06-28 10:17:21
【问题描述】:

我已经查看了Python docs 提供的信息,但我仍然有点困惑。有人可以发布示例代码来编写一个新文件,然后使用 pickle 将字典转储到其中吗?

【问题讨论】:

标签: python dictionary pickle


【解决方案1】:

试试这个:

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

【讨论】:

  • @houbysoft:你为什么要删除pickle.HIGHEST_PROTOCOL?
  • @Blender:对于这个级别的问题来说,无关紧要且不必要的复杂——普通用户使用默认设置就可以了。
  • @houbysoft:对于 Python 3 用户是正确的,但在 Python 2 上,使用默认协议 (0) 不仅在时间和空间上效率极低,而且实际上无法处理该协议的许多事情2+ 处理得很好(例如使用__slots__ 的新型类)。我并不是说您应该始终使用HIGHEST_PROTOCOL,但确保您不使用协议 0 或 1 实际上非常重要。
  • pickle.HIGHEST_PROTOCOL 究竟做了什么?
  • @BallpointBen:它会选择您的 Python 版本支持的最高协议版本:docs.python.org/3/library/pickle.html#data-stream-format
【解决方案2】:
>>> 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.

【讨论】:

  • 为什么是wb 而不是w+?
【解决方案3】:
import pickle

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

filename = "/foldername/filestore"

fileobj = open(filename, 'wb')

pickle.dump(dictobj, fileobj)

fileobj.close()

【讨论】:

    【解决方案4】:
    # 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"}
    

    【讨论】:

    • 在open()之后是否需要使用close()?
    • 一般来说是的。但是,在 CPython(您可能拥有的默认 python)中,只要文件对象过期(当没有引用它时),文件就会自动关闭。在这种情况下,由于 open() 返回后没有引用文件对象,因此一旦 load 返回,它将立即关闭。这不是好的做法,会导致其他系统出现问题
    • 为什么是wb 而不是w+?
    【解决方案5】:

    我发现腌制令人困惑(可能是因为我很厚)。不过,我发现这是可行的:

    myDictionaryString=str(myDictionary)
    

    然后您可以将其写入文本文件。我放弃了尝试使用 pickle,因为我收到错误告诉我将整数写入 .dat 文件。我很抱歉没有使用泡菜。

    【讨论】:

    • -1:应该按原样保存它(即,python 对象),以便我们稍后可以读取它,而无需等待数小时再次运行它。 Pickle 允许我们存储一个 python 对象以供以后读取。
    • 这是一个回到低质量帖子队列的旧答案。这不是一个糟糕的解决方案,因为它可能适用于非常简单的字典,但包含 dict 是非常合理的对象的更深层次(可能仅按名称打印)和/或没有任何或完整字符串表示的对象。
    • 补充@ti7 的观点,无论答案的技术优点如何,这篇文章都不是VLQ。如果有人认为这个答案不准确,他们应该投票和/或评论解释原因,不将其标记为 VLQ。
    【解决方案6】:

    一般来说,酸洗 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 内容的可挑选性之外,这很好)。

    【讨论】:

      【解决方案7】:
      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 的优点是文件变小了。这使得解酸有时更快。

      重要提示:pickle的最大文件大小约为2GB。

      另一种方式

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

      替代格式

      对于您的应用程序,以下内容可能很重要:

      • 其他编程语言的支持
      • 读/写性能
      • 紧凑性(文件大小)

      另请参阅:Comparison of data serialization formats

      如果您正在寻找一种制作配置文件的方法,您可能想阅读我的短文Configuration files in Python

      【讨论】:

      • 我认为 2GB 的限制在 protocol=4 或更高的情况下被移除了。
      • 为什么是wb 而不是w+?
      【解决方案8】:

      如果您只想将字典存储在单个文件中,请像这样使用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 中的不同文件并重新加载它们。

      更多详情请参阅documentation。

      【讨论】:

      • 为什么是wb 而不是w+?
      【解决方案9】:

      将 Python 数据(例如字典)转储到 pickle 文件的简单方法。

      import pickle
      
      your_dictionary = {}
      
      pickle.dump(your_dictionary, open('pickle_file_name.p', 'wb'))
      

      【讨论】:

      • 为什么是wb 而不是w+?
      【解决方案10】:

      仅供参考,Pandas 现在有一种保存泡菜的方法。

      我觉得这更容易。

      pd.to_pickle(object_to_save,'/temp/saved_pkl.pickle' )
      

      【讨论】:

        【解决方案11】:

        如果您想在不打开文件的情况下在一行中处理写入或读取:

          import joblib
        
          my_dict = {'hello': 'world'}
        
          joblib.dump(my_dict, "my_dict.pickle") # write pickle file
          my_dict_loaded = joblib.load("my_dict.pickle") # read pickle file
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-01-07
          相关资源
          最近更新 更多