Python 使用pickle将巨大的bigram字典保存到文件
我的一个朋友写了这个小节目。Python 使用pickle将巨大的bigram字典保存到文件,python,file,dictionary,pickle,Python,File,Dictionary,Pickle,我的一个朋友写了这个小节目。 textFile的大小为1.2GB(相当于7年的报纸)。 他成功地创建了字典,但无法使用pickle(程序挂起)将其写入文件 希望这有帮助。现在的策略改为使用mysql,因为sqlite无法工作(可能是因为它的大小)Pickle只用于编写完整(小)的对象。您的字典有点大,甚至无法保存在内存中,您最好使用数据库,这样您就可以逐个存储和检索条目,而不是一次存储所有条目 可以从Python中使用的一些好的、易于集成的单文件数据库格式是或其中之一。最后一个类似于字典(即,您
textFile
的大小为1.2GB(相当于7年的报纸)。
他成功地创建了字典,但无法使用pickle(程序挂起)将其写入文件
希望这有帮助。现在的策略改为使用mysql,因为sqlite无法工作(可能是因为它的大小)Pickle只用于编写完整(小)的对象。您的字典有点大,甚至无法保存在内存中,您最好使用数据库,这样您就可以逐个存储和检索条目,而不是一次存储所有条目
可以从Python中使用的一些好的、易于集成的单文件数据库格式是或其中之一。最后一个类似于字典(即,您可以读取和写入键/值对),但将磁盘用作存储,而不是1.2 Gb的内存。您真的需要内存中的全部数据吗?如果你想使用字典/pickle方法,你可以用简单的方式将其拆分,比如每年一个文件,每个月一个文件 另外,请记住,字典没有排序,您可能会遇到排序这一数据量的问题。如果您想搜索或排序数据,当然 无论如何,我认为前面提到的数据库方法是最灵活的方法,特别是从长远来看…如果您真的非常想使用字典式语义,请尝试SQLAlchemy的
associationproxy
。以下(相当长的)代码段将词典翻译成条目表中的键、值对。我不知道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
给予
一种解决办法是用泡菜代替泡菜。这是一个纯Python解决方案,保留了非常Python的语法。我认为这是下一步从搁置和他们的同类。它将处理您正在谈论的数据大小。其大小限制为每个字段2 GB(每个字段存储在单独的文件中)。我从http://coverartarchive.org
尽管下载这么多图像速度很慢,pickle
在155MB的容量上没有问题:
$ ll
total 151756
-rw-rw-r-- 1 rick rick 155208082 Oct 10 10:04 ipc.pickle
当我不再只为一张CD下载图像时,我会回来用更大的pickle限制更新这个答案。不幸的是,我还没有找到任何说明酸洗限制的地方…如果你要处理大文件,为什么不使用数据库呢?另外,我看到您对同一个文件执行了两次for循环,这可能是多余的,并且增加了处理成本。为什么不描述一下您对示例输入文件所做的操作呢?ghostdog74,您可以看到2个语句,但在文件上只有一个循环:)在文件上迭代只是读取行(从实际位置),它不查找文件的开头。只需尝试一下(您的Python dict由磁盘上的DB支持,而不是RAM支持).Sqlite是一个完全关系数据库,而Berkeley DB不是,只是键/值。如果只是存储,我认为Berkeley是一个更好的选择,而如果您想进行一些查询并以更有条理的方式存储信息,sqlite则更合适。BerkeleyDB非常易变且难以管理,尤其是在数据量较大的情况下。即使对于单个字符串->字符串存储(BerkeleyDB就是这样),我也会使用SQLite,它会处理所有的BerkeleyDB管理。SQLite的作用不像字典。bsddb module()的Python页面说它不推荐使用。对于BSD DB,是否还有另一个未弃用的Python选项?列出了许多数据持久性模块。gdbm的gdbm
模块看起来非常相似,并且仍然受支持,我会选择这个模块。我正在考虑在python中使用SQLite3。不过,我不确定你的答案中与sqlalchemy
的关系。
{
"Hello": {"World": 1, "munde": 1},
"World": {"domination": 2},
"Total": {"World": 1},
}
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'}
$ ll
total 151756
-rw-rw-r-- 1 rick rick 155208082 Oct 10 10:04 ipc.pickle