8

我的一个朋友写了这个小程序。大小为textFile1.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 不起作用(可能是因为大小)

4

5 回答 5

11

Pickle 仅用于编写完整的(小)对象。您的字典有点大,甚至无法保存在内存中,您最好使用数据库,这样您就可以一个一个地存储和检索条目,而不是一次全部存储和检索条目。

您可以从 Python 中使用的一些良好且易于集成的单一文件数据库格式是SQLiteDBM 变体之一。最后一个就像字典一样(即您可以读取和写入键/值对),但使用磁盘作为存储而不是 1.2 GB 的内存。

于 2010-01-21T10:11:50.670 回答
1

你真的需要内存中的全部数据吗?如果你想要字典/泡菜方法,你可以用简单的方式分割它,比如每年或每月一个文件。

另外,请记住字典没有排序,您可能会遇到必须对大量数据进行排序的问题。如果您想搜索或排序数据,当然......

无论如何,我认为之前评论的数据库方法是最灵活的一种,特别是从长远来看......

于 2010-01-21T10:41:50.440 回答
1

一种解决方案是使用buzhug代替泡菜。这是一个纯 Python 解决方案,并保留了非常 Pythonic 的语法。我认为这是从搁置及其同类产品升级的下一步。它将处理您正在谈论的数据大小。其大小限制为每个字段 2 GB(每个字段存储在单独的文件中)。

于 2010-01-21T14:52:56.953 回答
0

如果您真的非常想使用像语义这样的字典,请尝试使用 SQLAlchemy 的associationproxy. 以下(相当长的)代码将您的字典转换为-Table中的键、值对entries。我不知道 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'}
于 2010-01-21T14:20:12.890 回答
0

我从其中捕获图像http://coverartarchive.org,尽管下载这么多图像很慢,但pickle155 MB 没有问题:

$ ll
total 151756
-rw-rw-r--  1 rick rick 155208082 Oct 10 10:04 ipc.pickle

当我不再只为一张 CD 下载图像时,我会回来并用更大的 pickle 限制更新这个答案。不幸的是,我还没有找到任何说明酸洗限制的地方......

于 2020-10-10T20:55:49.317 回答