【问题标题】:how to save a dictionary in pickle如何在泡菜中保存字典
【发布时间】:2014-07-31 15:42:40
【问题描述】:

我正在尝试使用 Pickle 将字典保存在文件中。保存字典的代码运行没有任何问题,但是当我尝试从 Python shell 中的文件中检索字典时,出现 EOF 错误:

>>> import pprint
>>> pkl_file = open('data.pkl', 'rb')
>>> data1 = pickle.load(pkl_file)
 Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
     File "/usr/lib/python2.7/pickle.py", line 1378, in load
     return Unpickler(file).load()
     File "/usr/lib/python2.7/pickle.py", line 858, in load
      dispatch[key](self)
      File "/usr/lib/python2.7/pickle.py", line 880, in load_eof
      raise EOFError
      EOFError

我的代码如下。

它计算每个单词的频率和数据的日期(日期是文件名。)然后将单词保存为字典的键,并将 (freq,date) 的元组保存为每个键的值。现在我想用这本词典作为我工作另一部分的输入:

def pathFilesList():
    source='StemmedDataset'
    retList = []
    for r,d,f in os.walk(source):
        for files in f:
            retList.append(os.path.join(r, files))
    return retList

def parsing():
    fileList = pathFilesList()
    for f in fileList:
        print "Processing file: " + str(f)
        fileWordList = []
        fileWordSet = set()
        fw=codecs.open(f,'r', encoding='utf-8')
        fLines = fw.readlines()
        for line in fLines:
            sWord = line.strip()
            fileWordList.append(sWord)
            if sWord not in fileWordSet:
                fileWordSet.add(sWord)
        for stemWord in fileWordSet:
            stemFreq = fileWordList.count(stemWord)
            if stemWord not in wordDict:
                wordDict[stemWord] = [(f[15:-4], stemFreq)]
            else:
                wordDict[stemWord].append((f[15:-4], stemFreq))
        fw.close()

if __name__ == "__main__":
    parsing()
    output = open('data.pkl', 'wb')
    pickle.dump(wordDict, output)
    output.close()

你认为问题是什么?

【问题讨论】:

  • 您确定文件已关闭/刷新吗?
  • 以这种方式使用pickle 模块转储和加载WordDict 应该没问题。在转储字典之前,我会先查看一下字典中的内容,看看它的内容是否有效。
  • 是的,它是有效的。一旦我将它保存在 .txt 文件中并检查过它。
  • 可能是换行问题吗?查看this question

标签: python pickle


【解决方案1】:

由于这是 Python2,您通常必须更明确地说明您的源代码是用什么编码编写的。引用的 PEP-0263 对此进行了详细说明。我的建议是您尝试将以下内容添加到 unpickle.py 的前两行

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# The rest of your code....

顺便说一句,如果您要大量使用非 ascii 字符,那么改用 Python3 可能是个好主意。

【讨论】:

    【解决方案2】:
    # Added some code and comments.  To make the code more complete.
    # Using collections.Counter to count words.
    
    import os.path
    import codecs
    import pickle
    from collections import Counter
    
    wordDict = {}
    
    def pathFilesList():
        source='StemmedDataset'
        retList = []
        for r, d, f in os.walk(source):
            for files in f:
                retList.append(os.path.join(r, files))
        return retList
    
    # Starts to parse a corpus, it counts the frequency of each word and
    # the date of the data (the date is the file name.) then saves words
    # as keys of dictionary and the tuple of (freq,date) as values of each
    # key.
    def parsing():
        fileList = pathFilesList()
        for f in fileList:
            date_stamp = f[15:-4]
            print "Processing file: " + str(f)
            fileWordList = []
            fileWordSet = set()
            # One word per line, strip space. No empty lines.
            fw = codecs.open(f, mode = 'r' , encoding='utf-8')
            fileWords = Counter(w for w in fw.read().split())
            # For each unique word, count occurance and store in dict.
            for stemWord, stemFreq in fileWords.items():
                if stemWord not in wordDict:
                    wordDict[stemWord] = [(date_stamp, stemFreq)]
                else:
                    wordDict[stemWord].append((date_stamp, stemFreq))
            # Close file and do next.
            fw.close()
    
    
    if __name__ == "__main__":
        # Parse all files and store in wordDict.
        parsing()
    
        output = open('data.pkl', 'wb')
    
        # Assume wordDict is global.
        print "Dumping wordDict of size {0}".format(len(wordDict))
        pickle.dump(wordDict, output)
    
        output.close()
    

    【讨论】:

    • 这应该让你知道你倾倒的字典有多大。一些小的示例文件将有助于解决您的问题。可以发一下吗?
    • 谢谢你的回答,现在我试试这个方法。它应该是一个非常大的文件,因为我已经解析了 3206 个文本文件,并且一旦我将输出(字典)保存为 .txt 文件,它就是 256 MB。所以我认为这是一个很大的。我想发布一些我创建的示例文件,但我不能发布它们:-(
    • 新版本使用collections.Counters。可能包含障碍,因为此代码刚刚在干燥的地面上运行...
    • 在使用python 2.7.6.进行最小测试运行后更正了代码
    • 谢谢。我会运行这段代码,我会告诉结果。
    【解决方案3】:

    如果您正在寻找可以将大型数据字典保存到磁盘或数据库,并且可以利用酸洗和编码(编解码器和哈希图)的东西,那么您可能需要查看klepto

    klepto 为写入数据库提供字典抽象,包括将文件系统视为数据库(即将整个字典写入单个文件,或将每个条目写入其自己的文件)。对于大数据,我经常选择将字典表示为我的文件系统上的一个目录,并让每个条目都是一个文件。 klepto 还提供缓存算法,因此如果您为字典使用文件系统后端,则可以通过使用内存缓存来避免一些速度损失。

    >>> from klepto.archives import dir_archive
    >>> d = {'a':1, 'b':2, 'c':map, 'd':None}
    >>> # map a dict to a filesystem directory
    >>> demo = dir_archive('demo', d, serialized=True) 
    >>> demo['a']
    1
    >>> demo['c']
    <built-in function map>
    >>> demo          
    dir_archive('demo', {'a': 1, 'c': <built-in function map>, 'b': 2, 'd': None}, cached=True)
    >>> # is set to cache to memory, so use 'dump' to dump to the filesystem 
    >>> demo.dump()
    >>> del demo
    >>> 
    >>> demo = dir_archive('demo', {}, serialized=True)
    >>> demo
    dir_archive('demo', {}, cached=True)
    >>> # demo is empty, load from disk
    >>> demo.load()
    >>> demo
    dir_archive('demo', {'a': 1, 'c': <built-in function map>, 'b': 2, 'd': None}, cached=True)
    >>> demo['c']
    <built-in function map>
    >>> 
    

    klepto 还具有其他标志,例如 compressionmemmode,可用于自定义数据的存储方式(例如压缩级别、内存映射模式等)。 使用(MySQL 等)数据库作为后端而不是文件系统同样容易(完全相同的界面)。您还可以关闭内存缓存,因此每次读/写都直接进入存档,只需设置cached=False

    klepto 通过构建自定义keymap 提供自定义编码的访问权限。

    >>> from klepto.keymaps import *
    >>> 
    >>> s = stringmap(encoding='hex_codec')
    >>> x = [1,2,'3',min]
    >>> s(x)
    '285b312c20322c202733272c203c6275696c742d696e2066756e6374696f6e206d696e3e5d2c29'
    >>> p = picklemap(serializer='dill')
    >>> p(x)
    '\x80\x02]q\x00(K\x01K\x02U\x013q\x01c__builtin__\nmin\nq\x02e\x85q\x03.'
    >>> sp = s+p
    >>> sp(x)
    '\x80\x02UT28285b312c20322c202733272c203c6275696c742d696e2066756e6374696f6e206d696e3e5d2c292c29q\x00.' 
    

    在此处获取kleptohttps://github.com/uqfoundation

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-18
      相关资源
      最近更新 更多