我的一个朋友写了这个小程序。
textFile
的大小为1.2GB(7年报纸)。
他成功地设法创建了字典,但他不能使用pickle(程序挂起)将其写入文件。
import sys
import string
import cPickle as pickle
biGramDict = {}
textFile = open(str(sys.argv[1]), 'r')
biGramDictFile = open(str(sys.argv[2]), 'w')
for line in textFile:
if (line.find('<s>')!=-1):
old = None
for line2 in textFile:
if (line2.find('</s>')!=-1):
break
else:
line2=line2.strip()
if line2 not in string.punctuation:
if old != None:
if old not in biGramDict:
biGramDict[old] = {}
if line2 not in biGramDict[old]:
biGramDict[old][line2] = 0
biGramDict[old][line2]+=1
old=line2
textFile.close()
print "going to pickle..."
pickle.dump(biGramDict, biGramDictFile,2)
print "pickle done. now load it..."
biGramDictFile.close()
biGramDictFile = open(str(sys.argv[2]), 'r')
newBiGramDict = pickle.load(biGramDictFile)
提前感谢。
修改
对于任何感兴趣的人,我将简要解释这个程序的作用。
假设您的文件格式大致如下:
<s>
Hello
,
World
!
</s>
<s>
Hello
,
munde
!
</s>
<s>
World
domination
.
</s>
<s>
Total
World
domination
!
</s>
<s>
是句子分隔符。 生成biGramDictionary供以后使用。
像这样的东西:
{
"Hello": {"World": 1, "munde": 1},
"World": {"domination": 2},
"Total": {"World": 1},
}
希望这会有所帮助。现在,策略改为使用mysql,因为sqlite不起作用(可能是因为它的大小)
答案 0 :(得分:10)
Pickle仅用于编写完整(小)对象。您的字典有点大,甚至可以保留在内存中,您最好使用数据库,这样您就可以逐个存储和检索条目,而不是一次性存储和删除。
您可以在Python中使用的一些优秀且易于集成的单一文件数据库格式为SQLite或其中一个DBM variants。最后一个就像一个字典(即你可以读取和写入键/值对),但是使用磁盘作为存储而不是1.2 GB的内存。
答案 1 :(得分:1)
你真的需要内存中的全部数据吗?如果你想要字典/泡菜方法,你可以用天真的方式将它分开,例如每个月每个月一个文件。
另外,请记住,字典没有排序,您可能会遇到必须对大量数据进行排序的问题。如果您想搜索或排序数据,当然......
无论如何,我认为之前评论过的数据库方法是最灵活的,特别是从长远来看......
答案 2 :(得分:1)
一种解决方案是使用buzhug而不是pickle。它是一个纯Python解决方案,并保留了非常Pythonic语法。我认为这是从搁置及其同类的下一步。它将处理您正在谈论的数据大小。它的大小限制是每个字段2 GB(每个字段存储在一个单独的文件中)。
答案 3 :(得分:0)
如果真的,真的想要使用像语义这样的字典,请尝试SQLAlchemy的associationproxy
。以下(相当长的)代码将您的字典转换为entries
- 表中的 Key,Value-Pairs 。我不知道SQLAlchemy如何处理你的大词典,但SQLite应该能够很好地处理它。
from sqlalchemy import create_engine, MetaData
from sqlalchemy import Table, Column, Integer, ForeignKey, Unicode, UnicodeText
from sqlalchemy.orm import mapper, sessionmaker, scoped_session, Query, relation
from sqlalchemy.orm.collections import column_mapped_collection
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.schema import UniqueConstraint
engine = create_engine('sqlite:///newspapers.db')
metadata = MetaData()
metadata.bind = engine
Session = scoped_session(sessionmaker(engine))
session = Session()
newspapers = Table('newspapers', metadata,
Column('newspaper_id', Integer, primary_key=True),
Column('newspaper_name', Unicode(128)),
)
entries = Table('entries', metadata,
Column('entry_id', Integer, primary_key=True),
Column('newspaper_id', Integer, ForeignKey('newspapers.newspaper_id')),
Column('entry_key', Unicode(255)),
Column('entry_value', UnicodeText),
UniqueConstraint('entry_key', 'entry_value', name="pair"),
)
class Base(object):
def __init__(self, **kw):
for key, value in kw.items():
setattr(self, key, value)
query = Session.query_property(Query)
def create_entry(key, value):
return Entry(entry_key=key, entry_value=value)
class Newspaper(Base):
entries = association_proxy('entry_dict', 'entry_value',
creator=create_entry)
class Entry(Base):
pass
mapper(Newspaper, newspapers, properties={
'entry_dict': relation(Entry,
collection_class=column_mapped_collection(entries.c.entry_key)),
})
mapper(Entry, entries)
metadata.create_all()
dictionary = {
u'foo': u'bar',
u'baz': u'quux'
}
roll = Newspaper(newspaper_name=u"The Toilet Roll")
session.add(roll)
session.flush()
roll.entries = dictionary
session.flush()
for entry in Entry.query.all():
print entry.entry_key, entry.entry_value
session.commit()
session.expire_all()
print Newspaper.query.filter_by(newspaper_id=1).one().entries
给出
foo bar
baz quux
{u'foo': u'bar', u'baz': u'quux'}
答案 4 :(得分:0)
我从http://coverartarchive.org
捕获了图像,尽管下载速度很慢,但是pickle
的155 MB容量没有问题:
$ ll
total 151756
-rw-rw-r-- 1 rick rick 155208082 Oct 10 10:04 ipc.pickle
当我不再只是下载一张CD的图像时,我会回来并用更大的泡菜限制来更新此答案。不幸的是,我还没有找到说明酸洗极限的地方...