pkl how extension example custom python recursion tree pickle depth

python - how - pkl file



Alcanzar la profundidad máxima de recursión con Pickle/cPickle (5)

De los documentos :

Intentar recuperar una estructura de datos altamente recursiva puede exceder la profundidad máxima de recursión, en este caso se generará un RuntimeError. Puede elevar cuidadosamente este límite con sys.setrecursionlimit() .

Aunque su implementación de trie puede ser simple, usa la recursión y puede generar problemas al convertirla a una estructura de datos persistente.

Mi recomendación sería continuar elevando el límite de recursión para ver si hay un límite superior para los datos con los que está trabajando y la implementación que está utilizando.

Aparte de eso, puedes intentar cambiar la implementación de tu árbol para que sea "menos recursivo", si es posible, o escribir una implementación adicional que tenga incorporada la persistencia de los datos (usa los encuadres y los shelves en tu implementación). Espero que ayude

El trasfondo: estoy construyendo un trie para representar un diccionario, usando un algoritmo de construcción mínimo. La lista de entrada es de 4.3M utf-8 strings, ordenados lexicográficamente. El gráfico resultante es acíclico y tiene una profundidad máxima de 638 nodos. La primera línea de mi script establece el límite de recursión en 1100 a través de sys.setrecursionlimit() .

El problema: me gustaría poder serializar mi trie en el disco, así puedo cargarlo en la memoria sin tener que reconstruir desde cero (aproximadamente 22 minutos). He probado tanto pickle.dump() como cPickle.dump() , con el texto y los protocolos binarios. Cada vez, obtengo un seguimiento de pila que se ve así:

File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/pickle.py", line 649, in save_dict self._batch_setitems(obj.iteritems()) File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/pickle.py", line 663, in _batch_setitems save(v) File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/pickle.py", line 286, in save f(self, obj) # Call unbound method with explicit self File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/pickle.py", line 725, in save_inst save(stuff) File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/pickle.py", line 286, in save f(self, obj) # Call unbound method with explicit self File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/pickle.py", line 648, in save_dict self.memoize(obj) RuntimeError: maximum recursion depth exceeded

Mis estructuras de datos son relativamente simples: trie contiene una referencia al estado de inicio y define algunos métodos. dfa_state contiene un campo booleano, un campo de cadena y una asignación de diccionario de etiqueta a estado.

No estoy muy familiarizado con el funcionamiento interno del pickle . ¿Mi profundidad de recursión máxima debe ser mayor / igual a n veces la profundidad del trie para algunos n? ¿O podría ser causado por algo más que desconozco?

Actualización: Establecer la profundidad de recursión en 3000 no ayudó, por lo que esta avenida no parece prometedora.

Actualización 2: Ustedes tenían razón; Estaba siendo miope al suponer que Pickle usaría una profundidad de anidamiento pequeña debido a las limitaciones de recursión predeterminadas. 10,000 hizo el truco.


Mis necesidades eran algo inmediatas, así que resolví este problema guardando mi diccionario en formato .txt. Lo único es que cuando cargas tu archivo de nuevo, tienes que volver a transformarlo en un diccionario.

import json # Saving the dictionary with open(''filename.txt'', ''w'') as file_handle: file_handle.write(str(dictionary)) # Importing the .txt file with open(''filename.txt'', ''r'') as file_handle: f = ''"'' + file_handle.read() + ''"'' # From .txt file to dictionary dictionary = eval(json.loads(f))

Si esto no funciona, puede intentar exportar el diccionario utilizando el formato json.


Pickle necesita caminar recursivamente por su trie. Si Pickle usa solo 5 niveles de llamadas de función para hacer el trabajo, su trie de profundidad 638 necesitará el nivel establecido en más de 3000.

Pruebe con un número mucho mayor, el límite de recursión realmente está ahí para proteger a los usuarios de tener que esperar demasiado si la recursión cae en un agujero infinito.

Pickle maneja ciclos bien, así que no importa incluso si tu trie tenía un ciclo allí


Verifica que tu estructura sea acíclica.

Podría intentar subir el límite aún más. Hay un máximo difícil que depende de la plataforma, pero intentar 50000 sería razonable.

También intente decapando una versión trivialmente pequeña de su trie. Si pickle muere a pesar de que solo almacena un par de palabras de tres letras, entonces sabes que hay un problema fundamental con tu trie y no con el pickle. Pero si solo ocurre cuando intenta almacenar 10k palabras, entonces podría ser la culpa de una limitación de la plataforma encurtido.


El tamaño de la pila también se debe aumentar con resource.setrlimit para evitar el error de seg

Si usa simplemente sys.setrecursionlimit , aún puede segfault si alcanza el tamaño máximo de pila permitido por el kernel de Linux.

Este valor se puede aumentar con resource.setrlimit como se menciona en: Configuración de stacksize en una secuencia de comandos python

import pickle import resource import sys print resource.getrlimit(resource.RLIMIT_STACK) print sys.getrecursionlimit() max_rec = 0x100000 # May segfault without this line. 0x100 is a guess at the size of each stack frame. resource.setrlimit(resource.RLIMIT_STACK, [0x100 * max_rec, resource.RLIM_INFINITY]) sys.setrecursionlimit(max_rec) a = [] # 0x10 is to account for subfunctions called inside `pickle`. for i in xrange(max_rec / 0x10): a = [a] print pickle.dumps(a, -1)

Vea también: ¿Cuál es la profundidad de recursión máxima en Python y cómo aumentarla?

El valor máximo predeterminado para mí es 8Mb.

Probado en Ubuntu 16.10, Python 2.7.12.