El problema que estoy teniendo es que tengo un gran archivo pickle (2,6 Gb) que estoy tratando de abrir pero cada vez que puedo hacerlo me sale un error de memoria. Ahora me doy cuenta de que debería haber usado una base de datos para almacenar toda la información, pero es demasiado tarde ahora. El archivo pickle contiene las fechas y el texto del Congreso de estados UNIDOS de registro que se arrastró desde el internet (tomó cerca de 2 semanas para que se ejecute). Hay alguna manera de que pueda acceder a la información que me dejó en el archivo pickle de forma incremental o una manera de convertir el archivo pickle en una base de datos sql o algo que me pueda abrir sin tener que volver a introducir todos los datos. Yo realmente no quiero tener que pasar otras 2 semanas un nuevo rastreo del congreso de registro e imputación de los datos en una base de datos.

Muchísimas gracias por tu ayuda

EDITAR*

código de cómo el objeto se pone en escabeche:

def save_objects(objects): 
    with open('objects.pkl', 'wb') as output: 
        pickle.dump(objects, output, pickle.HIGHEST_PROTOCOL)

def Main():   
    Links()
    file = open("datafile.txt", "w")
    objects=[]
    with open('links2.txt', 'rb') as infile:
        for link in infile: 
            print link
            title,text,date=Get_full_text(link)
            article=Doccument(title,date,text)
            if text != None:
                write_to_text(date,text)
                objects.append(article)
                save_objects(objects)

Este es el programa con el error:

def Main():
    file= open('objects1.pkl', 'rb') 
    object = pickle.load(file)
La cantidad de RAM que hace la máquina en que se ejecuta el programa?
El uso de sqlite, a pickle un 2,6 Gb de archivo es bastante cercano a la locura. Sqlite es bastante fácil de conseguir alrededor 😉
Compartir los datos y me van a unpickle para usted o alquiler un gran AWS máquina para el trabajo. Estoy bastante seguro de que @IanAuld está bien.. que falta de memoria.
Se puede proporcionar un programa de ejemplo que muestra precisamente cómo «objeto de dumping en el archivo pickle de forma incremental»?
Vamos a pensar en ello, por favor proporcione una breve programa completo que demuestra el error de la memoria que están viendo.

OriginalEl autor Vineeth Bhuvanagiri | 2014-10-16

2 Comentarios

  1. 29

    Parece que eres un poco un lío! ;-). Esperemos que después de esto, usted NUNCA tendrá que UTILIZAR la SALMUERA NUNCA. Simplemente no es una muy buena formato de almacenamiento de datos.

    De todos modos, para que esta respuesta estoy asumiendo que su Document clase parece un poco a esto. Si no, el comentario con tu Document clase:

    class Document(object): # <-- object part is very important! If it's not there, the format is different!
        def __init__(self, title, date, text): # assuming all strings
            self.title = title
            self.date = date
            self.text = text

    De todos modos, he hecho algunas simples de los datos de prueba con esta clase:

    d = [Document(title='foo', text='foo is good', date='1/1/1'), Document(title='bar', text='bar is better', date='2/2/2'), Document(title='baz', text='no one likes baz :(', date='3/3/3')]

    Escabeche con formato 2 (pickle.HIGHEST_PROTOCOL para Python 2.x)

    >>> s = pickle.dumps(d, 2)
    >>> s
    '\x80\x02]q\x00(c__main__\nDocument\nq\x01)\x81q\x02}q\x03(U\x04dateq\x04U\x051/1/1q\x05U\x04textq\x06U\x0bfoo is goodq\x07U\x05titleq\x08U\x03fooq\tubh\x01)\x81q\n}q\x0b(h\x04U\x052/2/2q\x0ch\x06U\rbar is betterq\rh\x08U\x03barq\x0eubh\x01)\x81q\x0f}q\x10(h\x04U\x053/3/3q\x11h\x06U\x13no one likes baz :(q\x12h\x08U\x03bazq\x13ube.'

    Y desmontado con pickletools:

    >>> pickletools.dis(s)
    0: \x80 PROTO      2
    2: ]    EMPTY_LIST
    3: q    BINPUT     0
    5: (    MARK
    6: c        GLOBAL     '__main__ Document'
    25: q        BINPUT     1
    27: )        EMPTY_TUPLE
    28: \x81     NEWOBJ
    29: q        BINPUT     2
    31: }        EMPTY_DICT
    32: q        BINPUT     3
    34: (        MARK
    35: U            SHORT_BINSTRING 'date'
    41: q            BINPUT     4
    43: U            SHORT_BINSTRING '1/1/1'
    50: q            BINPUT     5
    52: U            SHORT_BINSTRING 'text'
    58: q            BINPUT     6
    60: U            SHORT_BINSTRING 'foo is good'
    73: q            BINPUT     7
    75: U            SHORT_BINSTRING 'title'
    82: q            BINPUT     8
    84: U            SHORT_BINSTRING 'foo'
    89: q            BINPUT     9
    91: u            SETITEMS   (MARK at 34)
    92: b        BUILD
    93: h        BINGET     1
    95: )        EMPTY_TUPLE
    96: \x81     NEWOBJ
    97: q        BINPUT     10
    99: }        EMPTY_DICT
    100: q        BINPUT     11
    102: (        MARK
    103: h            BINGET     4
    105: U            SHORT_BINSTRING '2/2/2'
    112: q            BINPUT     12
    114: h            BINGET     6
    116: U            SHORT_BINSTRING 'bar is better'
    131: q            BINPUT     13
    133: h            BINGET     8
    135: U            SHORT_BINSTRING 'bar'
    140: q            BINPUT     14
    142: u            SETITEMS   (MARK at 102)
    143: b        BUILD
    144: h        BINGET     1
    146: )        EMPTY_TUPLE
    147: \x81     NEWOBJ
    148: q        BINPUT     15
    150: }        EMPTY_DICT
    151: q        BINPUT     16
    153: (        MARK
    154: h            BINGET     4
    156: U            SHORT_BINSTRING '3/3/3'
    163: q            BINPUT     17
    165: h            BINGET     6
    167: U            SHORT_BINSTRING 'no one likes baz :('
    188: q            BINPUT     18
    190: h            BINGET     8
    192: U            SHORT_BINSTRING 'baz'
    197: q            BINPUT     19
    199: u            SETITEMS   (MARK at 153)
    200: b        BUILD
    201: e        APPENDS    (MARK at 5)
    202: .    STOP

    Parece complejo! Pero realmente, no es tan malo. pickle es, básicamente, una pila de máquina, cada ALL_CAPS identificador que se ve es un opcode, que manipula a la interna de la «pila» de alguna manera para la decodificación. Si estamos tratando de analizar algunas de estructura compleja, que esto es lo más importante, pero por suerte estamos a sólo una simple lista de esencialmente-tuplas. Todo este «código» que está haciendo es construir un montón de objetos en la pila y, a continuación, empujando la totalidad de la pila en una lista.

    La única cosa que no tienen que preocuparse por que son las ‘BINPUT’ /’BINGET’ opcodes que ver esparcidos alrededor. Básicamente, estos son para ‘memoization’, para reducir la huella de datos, pickle guarda cadenas con BINPUT <id>, y luego si vienen de nuevo, en lugar de volver a dejarlos, simplemente pone un BINGET <id> a recuperar desde la memoria caché.

    También, otra complicación! No hay más que SHORT_BINSTRING – no es normal BINSTRING para las cadenas > 256 bytes, y también un poco de diversión unicode variantes también. Voy a asumir que usted está usando Python 2 con todas las cadenas de caracteres ASCII. De nuevo, comentar que si esto no es una suposición correcta.

    OK, por lo que necesita para transmitir el archivo hasta que llegamos a un ‘\81’ bytes (NEWOBJ). Entonces, necesitamos escanear hacia adelante hasta que llegamos a un ‘(‘ (MARK) carácter. Entonces, hasta que llegamos a una ‘u’ (SETITEMS), leemos pares de clave/valor de cadenas – no debe ser de 3 pares en total, uno para cada campo.

    Entonces, vamos a hacer esto. Aquí está mi script para leer pickle de datos en streaming de la moda. Es lejos de ser perfecto, ya que sólo hackeado juntos por esta respuesta, y usted tendrá que modificar mucho, pero es un buen comienzo.

    pickledata = '\x80\x02]q\x00(c__main__\nDocument\nq\x01)\x81q\x02}q\x03(U\x04dateq\x04U\x051/1/1q\x05U\x04textq\x06U\x0bfoo is goodq\x07U\x05titleq\x08U\x03fooq\tubh\x01)\x81q\n}q\x0b(h\x04U\x052/2/2q\x0ch\x06T\x14\x05\x00\x00bar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterq\rh\x08U\x03barq\x0eubh\x01)\x81q\x0f}q\x10(h\x04U\x053/3/3q\x11h\x06U\x13no one likes baz :(q\x12h\x08U\x03bazq\x13ube.'
    # simulate a file here
    import StringIO
    picklefile = StringIO.StringIO(pickledata)
    import pickle # just for opcode names
    import struct # binary unpacking
    def try_memo(f, v, cache):
    opcode = f.read(1)
    if opcode == pickle.BINPUT:
    cache[f.read(1)] = v
    elif opcode == pickle.LONG_BINPUT:
    print 'skipping LONG_BINPUT to save memory, LONG_BINGET will probably not be used'
    f.read(4)
    else:
    f.seek(f.tell() - 1) # rewind
    def try_read_string(f, opcode, cache):
    if opcode in [ pickle.SHORT_BINSTRING, pickle.BINSTRING ]:
    length_type = 'b' if opcode == pickle.SHORT_BINSTRING else 'i'
    str_length = struct.unpack(length_type, f.read(struct.calcsize(length_type)))[0]
    value = f.read(str_length)
    try_memo(f, value, memo_cache)
    return value
    elif opcode == pickle.BINGET:
    return memo_cache[f.read(1)]
    elif opcide == pickle.LONG_BINGET:
    raise Exception('Unexpected LONG_BINGET? Key ' + f.read(4))
    else:
    raise Exception('Invalid opcode ' + opcode + ' at pos ' + str(f.tell()))
    memo_cache = {}
    while True:
    c = picklefile.read(1)
    if c == pickle.NEWOBJ:
    while picklefile.read(1) != pickle.MARK:
    pass # scan forward to field instantiation
    fields = {}
    while True:
    opcode = picklefile.read(1)
    if opcode == pickle.SETITEMS:
    break
    key = try_read_string(picklefile, opcode, memo_cache)
    value = try_read_string(picklefile, picklefile.read(1), memo_cache)
    fields[key] = value
    print 'Document', fields
    # insert to sqllite
    elif c == pickle.STOP:
    break

    Este correctamente lee mis datos de prueba en salmuera formato 2 (modificado de tener una larga cadena):

    $ python picklereader.py
    Document {'date': '1/1/1', 'text': 'foo is good', 'title': 'foo'}
    Document {'date': '2/2/2', 'text': 'bar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is better', 'title': 'bar'}
    Document {'date': '3/3/3', 'text': 'no one likes baz :(', 'title': 'baz'}

    Buena suerte!

    OriginalEl autor vgel

  2. 9

    No pickle sus datos de forma incremental. Usted curtido de sus datos monolíticamente y repetidamente. En cada vuelta del bucle, que destruyó lo que los datos de salida que tenía (open(...,'wb') destruye el archivo de salida), y re-escribió todos los datos de nuevo. Además, si el programa nunca se detuvo y luego se reinicia con la nueva entrada de datos, la edad de salida de datos se han perdido.

    No sé por qué objects no causar un error de memoria mientras se decapado, porque crece al mismo tamaño que el objeto que pickle.load() quiere crear.

    Aquí es cómo usted podría haber creado el archivo pickle de forma incremental:

    def save_objects(objects): 
    with open('objects.pkl', 'ab') as output:  # Note: `ab` appends the data
    pickle.dump(objects, output, pickle.HIGHEST_PROTOCOL)
    def Main():
    ...
    #objects=[] <-- lose the objects list
    with open('links2.txt', 'rb') as infile:
    for link in infile: 
    ... 
    save_objects(article)

    Entonces usted podría tener de forma incremental leer el archivo pickle así:

    import pickle
    with open('objects.pkl', 'rb') as pickle_file:
    try:
    while True:
    article = pickle.load(pickle_file)
    print article
    except EOFError:
    pass

    Las opciones que puedo pensar son:

    • Intentar cPickle. Podría ser de ayuda.
    • Tratar de streaming-pickle
    • Leer su archivo pickle en un entorno de 64 bits con montones y montones de RAM
    • Volver a rastrear los datos originales, esta vez realmente incrementalmente el almacenamiento de los datos, o su almacenamiento en una base de datos.
      Sin la ineficiencia de la constante de re-escribir su pickle archivo de salida, su rastreo podría ir significativamente más rápido esta vez.
    gracias un montón. Me encontré con el rastreador en un equipo y, a continuación, trató de ver el archivo pickle en otra máquina. Funciona en la máquina original que tiene más memoria.
    Oh, entonces la respuesta es obvia: extraer los datos del archivo pickle en el equipo original.

    OriginalEl autor Robᵩ

Dejar respuesta

Please enter your comment!
Please enter your name here