Guardando el enorme diccionario de bigtwigs para archivar usando pickle

un amigo mío escribió este pequeño progtwig. El textFile tiene un tamaño de 1.2GB (7 años de periódicos). Se las arregla para crear el diccionario con éxito, pero no puede escribirlo en un archivo usando pickle (lockings del progtwig).

 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('')!=-1): old = None for line2 in textFile: if (line2.find('')!=-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) 

gracias por adelantado.

EDITAR
Para cualquier persona interesada explicaré brevemente qué hace este progtwig. Suponiendo que tiene un archivo con un formato similar al siguiente:

  Hello , World !   Hello , munde !   World domination .   Total World domination !  
  • son separadores de oraciones.
  • una palabra por línea

se genera un biGramDictionary para su uso posterior.
algo como esto:

 { "Hello": {"World": 1, "munde": 1}, "World": {"domination": 2}, "Total": {"World": 1}, } 

espero que esto ayude. en este momento, la estrategia cambió a usar mysql porque sqlite simplemente no estaba funcionando (probablemente debido al tamaño)

Pickle es solo para escribir objetos completos (pequeños). Su diccionario es un poco grande para mantenerlo en la memoria, es mejor que use una base de datos para poder almacenar y recuperar las entradas una por una en lugar de todas a la vez.

Algunos formatos de base de datos únicos y fácilmente integrables que puede usar de Python son SQLite o una de las variantes de DBM . El último actúa como un diccionario (es decir, puede leer y escribir pares de clave / valor) pero utiliza el disco como almacenamiento en lugar de 1.2 GB de memoria.

¿Realmente necesitas todos los datos en la memoria? Podría dividirlo de manera ingenua, como un archivo por cada año o cada mes, si desea un enfoque de diccionario / pickle.

Además, recuerde que los diccionarios no están ordenados, puede tener problemas para ordenar esa cantidad de datos. En caso de que desee buscar u ordenar los datos, por supuesto …

De todos modos, creo que el enfoque de base de datos comentado anteriormente es el más flexible, especialmente a largo plazo …

Una solución es usar buzhug en lugar de pickle. Es una solución pura de Python y conserva una syntax muy pythonica. Pienso en ello como el siguiente paso desde la estantería y su clase. Manejará los tamaños de datos de los que está hablando. Su límite de tamaño es de 2 GB por campo (cada campo se almacena en un archivo separado).

Si realmente desea utilizar un diccionario como semántica, pruebe el proxy de associationproxy de SQLAlchemy. El siguiente fragmento de código (bastante largo) traduce su diccionario a Key, Value-Pairs en las entries -Table. No sé cómo SQLAlchemy hace frente a su gran diccionario, pero SQLite debería poder manejarlo muy bien.

 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 

da

 foo bar baz quux {u'foo': u'bar', u'baz': u'quux'}