Estoy casi seguro de que hay una solución simple para esto, pero he pasado horas leyendo y releyendo el mismo conjunto de resultados relacionados que don No responderé mi problema.Caminando/iterando sobre un diccionario anidado de profundidad arbitraria (el diccionario representa un árbol de directorio)
contexto de esta pregunta (incluido para la terminación pero no dude en saltarse este)
Esto ocurrió porque quiero que un usuario sea capaz de seleccionar un grupo de archivos dentro de un directorio (y también cualquier subdirectorio), y desafortunadamente la capacidad predeterminada de Tkinter para seleccionar múltiples archivos en un diálogo de archivo está quebrada en Windows 7 (http://bugs.python.org/issue8010).
Por lo tanto, estoy tratando de representar una estructura de directorio por un método alternativo (aún usando Tkinter): construir un facsímil de la estructura de directorios, hecho de casillas marcadas e indentadas (organizadas en un árbol). Así, un directorio de la siguiente manera:
\SomeRootDirectory
\foo.txt
\bar.txt
\Stories
\Horror
\rickscott.txt
\Trash
\notscary.txt
\Cyberpunk
\Poems
\doyoureadme.txt
se verá algo como esto (donde # representa un botón de verificación):
SomeRootDirectory
# foo.txt
# bar.txt
Stories
Horror
# rickscott.txt
Trash
# notscary.txt
Cyberpunk
Poems
# doyoureadme.txt
Construyendo el diccionario original de la estructura de directorios es fácil usando una cierta receta que encontré en ActiveState (ver a continuación), pero toco una pared cuando trato de iterar sobre el diccionario muy bien anidado que me queda. Y creo que necesito iterar sobre eso para llenar un cuadro Tkinter con una representación cuadriculada bonita del árbol. Luego espero cargar los diversos archivos de texto seleccionados por el usuario, interpretando qué casillas de verificación son verdaderas o falsas. Todo parece bastante fácil, excepto iterar sobre el diccionario sin para fijar la profundidad.
En términos más abstractos
Para hacer estos diccionarios anidados que estoy usando una receta ActiveState - http://code.activestate.com/recipes/577879/. Implementa os.walk para hacer diccionarios como este:
a={
'SomeRootDirectory': {
'foo.txt': None,
'bar.txt': None,
'Stories': {
'Horror': {
'rickscott.txt' : None,
'Trash' : {
'notscary.txt' : None,
},
},
'Cyberpunk' : None
},
'Poems' : {
'doyoureadme.txt' : None
}
}
}
Después de lo cual estoy perplejo. Soy un novato de Python y un mero especialista en humanidades ... que en mi caso significa que la recursividad es muy confusa para mí. Así que miré y busqué recetas e intenté todo tipo de modificaciones de respuestas similares, pero fue en vano. Necesito poder iterar sobre este diccionario para completar otra representación de él, y también para reconstruir las referencias a los archivos después de hacer eso (es decir, después de que el usuario haya seleccionado qué archivos).
¡Mis disculpas si esto es demasiado detallado! ¡Gracias por tu ayuda!
solución adaptada de la respuesta de spicavigo
#distinguish between directory and file
dirtab = "/==="
filetab = "|---"
Parents={-1:"Root"}
def add_dir(level, parent, index, k):
print (dirtab*level)+k
def add_file(level, parent, index, k):
#Currently an empty folder gets passed to add_file; here's a quick treatment.
if "." in k:
print (filetab*level)+k
else:
print (dirtab*level)+k
def addemup(level=0, parent=-1, index=0, di={}):
for k in di:
index +=1
if di[k]:
Parents[index]=k
add_dir(level, parent, index, k)
addemup(level+1, index, index, di[k])
else:
add_file(level, parent, index, k)
addemup(di=a) #dictionary from above
Esto produce algo que creo que va a ser muy fácil de revisar en una representación Tkinter:
SomeRootDirectory
/===Poems
|---|---doyoureadme.txt
/===Stories
/===/===Horror
|---|---|---rickscott.txt
/===/===/===Trash
|---|---|---|---notscary.txt
/===/===Cyberpunk
|---foo.txt
|---bar.txt
Gracias, esta comunidad es increíble.
cuando iterar sobre el diccionario pares de valores clave (dentro de una función que toma como argumento el diccionario), se puede comprobar si el valor es un tipo de diccionario, si es sí, entonces llame a su función de nuevo, es decir, usa recursividad aquí y pasa el valor como diccionario a la función, de lo contrario procesa el valor ... esto debería resolver el problema de iteración de profundidad variable – avasal