Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Pickle转储没有内存错误的大型文件_Python_Memory_File Io_Pickle - Fatal编程技术网

Python Pickle转储没有内存错误的大型文件

Python Pickle转储没有内存错误的大型文件,python,memory,file-io,pickle,Python,Memory,File Io,Pickle,我有一个程序,我基本上是根据已知的情况调整某些事情发生的概率。我的数据文件已保存为pickle字典对象,位于Dictionary.txt 问题是,每次我运行程序时,它都会拉入Dictionary.txt,将其转换为Dictionary对象,进行编辑并覆盖Dictionary.txt。这相当占用内存,因为Dictionary.txt是123MB。当我倒垃圾时,我得到了记忆错误,当我把它拉进去时,一切似乎都很好 有没有更好(更有效)的编辑方法?(可能每次都不必覆盖整个文件) 有没有一种方法可以调用

我有一个程序,我基本上是根据已知的情况调整某些事情发生的概率。我的数据文件已保存为
pickle
字典对象,位于
Dictionary.txt

问题是,每次我运行程序时,它都会拉入
Dictionary.txt
,将其转换为Dictionary对象,进行编辑并覆盖
Dictionary.txt
。这相当占用内存,因为
Dictionary.txt
是123MB。当我倒垃圾时,我得到了记忆错误,当我把它拉进去时,一切似乎都很好

  • 有没有更好(更有效)的编辑方法?(可能每次都不必覆盖整个文件)

  • 有没有一种方法可以调用垃圾收集(通过
    gc
    模块)?(我已经通过
    gc.enable()
    自动启用了它)

  • 我知道除了
    readlines()
    之外,你还可以逐行阅读。当程序中已经有一个完整的字典对象文件时,是否有一种方法可以逐行递增地编辑字典

  • 还有其他解决办法吗


感谢您的时间。

如果您的键和值是字符串,则可以使用Python标准库中提供的嵌入式持久键值存储引擎之一。模块文档中的示例:

import anydbm

# Open database, creating it if necessary.
db = anydbm.open('cache', 'c')

# Record some values
db['www.python.org'] = 'Python Website'
db['www.cnn.com'] = 'Cable News Network'

# Loop through contents.  Other dictionary methods
# such as .keys(), .values() also work.
for k, v in db.iteritems():
    print k, '\t', v

# Storing a non-string key or value will raise an exception (most
# likely a TypeError).
db['www.yahoo.com'] = 4

# Close when done.
db.close()

您是否尝试过使用流式pickle:

我刚刚通过切换到流式pickle解决了一个类似的内存错误。

这个怎么样

import cPickle as pickle
p = pickle.Pickler(open("temp.p","wb")) 
p.fast = True 
p.dump(d) # d could be your dictionary or any file

我有内存错误,并使用protocol=2解决了它:


cPickle.dump(对象,文件,协议=2)

我最近遇到了这个问题。在使用ASCII和二进制协议2尝试cpickle之后,我发现,由于内存错误,在20+gb数据上训练的sci kit learn中的SVM没有进行酸洗。然而,dill方案似乎解决了这个问题。Dill不会为字典带来很多改进,但可能有助于流媒体。它意味着通过网络传输pickle字节

import dill

with open(path,'wb') as fp:
    dill.dump(outpath,fp)
    dill.load(fp)
如果效率存在问题,请尝试加载/保存到数据库。在这种情况下,您的存储解决方案可能是一个问题。123MB的容量应该可以。但是,如果机器内存有限,SQL提供对数据的快速、优化的包操作,通常支持多线程。
我的多核svm已保存。

我是名为
klepot
的软件包的作者(也是
dill
的作者)。
klepot
以非常简单的方式存储和检索对象,并为数据库、内存缓存和磁盘存储提供了一个简单的字典接口。下面,我将展示如何在“目录归档”中存储大型对象,这是一个文件系统目录,每个条目有一个文件。我选择序列化对象(速度较慢,但使用dill,因此几乎可以存储任何对象),并选择缓存。使用内存缓存使我能够快速访问目录归档文件,而不必将整个归档文件存储在内存中。与数据库或文件的交互可能很慢,但与内存的交互很快……而且您可以根据需要从存档中填充内存缓存

>>> import klepto
>>> d = klepto.archives.dir_archive('stuff', cached=True, serialized=True)
>>> d
dir_archive('stuff', {}, cached=True)
>>> import numpy
>>> # add three entries to the memory cache
>>> d['big1'] = numpy.arange(1000)
>>> d['big2'] = numpy.arange(1000)
>>> d['big3'] = numpy.arange(1000)
>>> # dump from memory cache to the on-disk archive
>>> d.dump()
>>> # clear the memory cache
>>> d.clear()
>>> d
dir_archive('stuff', {}, cached=True)
>>> # only load one entry to the cache from the archive
>>> d.load('big1')
>>> d['big1'][-3:]
array([997, 998, 999])
>>> 
klepot
提供对大量存储的快速灵活访问,如果存档允许并行访问(例如某些数据库),则您可以并行读取结果。在不同的并行进程或不同的机器上共享结果也很容易。这里我创建了第二个归档实例,指向同一个目录归档。在两个对象之间传递关键点很容易,并且在不同的过程中工作没有什么不同

>>> f = klepto.archives.dir_archive('stuff', cached=True, serialized=True)
>>> f
dir_archive('stuff', {}, cached=True)
>>> # add some small objects to the first cache  
>>> d['small1'] = lambda x:x**2
>>> d['small2'] = (1,2,3)
>>> # dump the objects to the archive
>>> d.dump()
>>> # load one of the small objects to the second cache
>>> f.load('small2')
>>> f       
dir_archive('stuff', {'small2': (1, 2, 3)}, cached=True)
您还可以选择不同级别的文件压缩,以及 您希望文件被内存映射。有很多不同的方法 选项,用于文件后端和数据库后端。接口 然而,这是相同的

关于垃圾收集和编辑词典部分的其他问题,这两种方法都可以通过
klepot
,因为您可以单独从内存缓存中加载和删除对象、转储、加载并与存档后端或任何其他词典方法同步

请参见此处的较长教程:


获取
klepot
此处:

以上所有答案对我都不起作用。我最终使用了Hickle,它是基于HDF5的pickle的替代品。它不是将数据保存到pickle,而是将数据保存到HDF5文件。API在大多数用例中都是相同的,它有一些非常酷的特性,比如压缩

pip install hickle
例如:

# Create a numpy array of data
array_obj = np.ones(32768, dtype='float32')

# Dump to file
hkl.dump(array_obj, 'test.hkl', mode='w')

# Load data
array_hkl = hkl.load('test.hkl')

我也有同样的问题。我使用joblib,工作就完成了。如果有人想知道其他的可能性

将模型保存到磁盘

from sklearn.externals import joblib
filename = 'finalized_model.sav'
joblib.dump(model, filename)  
过了一段时间。。。从磁盘加载模型

loaded_model = joblib.load(filename)
result = loaded_model.score(X_test, Y_test) 

print(result)

这可能看起来很琐碎,但如果您不喜欢,请尝试使用64位Python。

我尝试了这一点,并成功地对其进行了pickle处理,但当我尝试使用pickle.load(open(“temp”、“rb”))取消pickle时,出现了一个“ValueError:unsecure string pickle”错误。我了解到这可能是因为pickle没有关闭,但是Pickler实例没有属性“close”。您能帮我找出如何再次取消勾选文件吗?可能是因为文件对象从未关闭过吗?流式pickle似乎不太适合当前只有一个dictionary对象的情况。当它更适合(比如一个巨大的列表)时,普通的pickle也可以做到这一点,因为您可以将几个pickle一个接一个地转储到同一个文件中,请参见问题:有几个压缩库和其他库。就我个人而言,我喜欢dill和H5Py来处理大型对象。如果您使用的是scikit learn,并且必须使用基于字典的模型,那么您也可以使用joblib(仅适用于这些模型)。不适用于python 3.5
klepot
的klepot也可以转储到HDF5,类似于
hickle
,并且与python 3.x兼容。@omarfl