Обход / итерация по вложенному словарю произвольной глубины (словарь представляет собой дерево каталогов)

Я почти уверен, что есть простое решение для этого, но я провел часы, читая и перечитывая тот же набор связанных результатов, которые не совсем отвечают на мою проблему.

Контекст этого вопроса (включен для завершения, но не стесняйтесь его пропустить)

Это возникло, потому что я хочу, чтобы пользователь мог выбирать группу файлов из каталога (а также любого подкаталога), и, к сожалению, Tkinter по умолчанию возможность выбора нескольких файлов в диалоговом окне файла не работает в Windows 7 ( http://bugs.python.org/issue8010 ).

Таким образом, я пытаюсь представить структуру каталогов альтернативным методом (все еще используя Tkinter): создание факсимиле структуры каталогов, состоящей из помеченных флажков и полей с отступом (организованных в виде дерева). Таким образом, такой каталог:

\SomeRootDirectory
    \foo.txt
    \bar.txt
    \Stories
        \Horror
            \scary.txt
            \Trash
                \notscary.txt
        \Cyberpunk
    \Poems
        \doyoureadme.txt

будет выглядеть примерно так (где # представляет собой кнопку-флажок):

SomeRootDirectory
    # foo.txt
    # bar.txt
    Stories
        Horror
            # scary.txt
            Trash
                # notscary.txt
        Cyberpunk
    Poems
        # doyoureadme.txt

​​Создать исходный словарь из структуры каталогов легко, используя определенные рецепт, который я нашел в ActiveState (см. ниже), но я упираюсь в стену, когда пытаюсь перебрать красиво вложенный словарь, который у меня остался. И я думаю, мне нужно перебрать его, чтобы заполнить фрейм Tkinter довольно сетчатым представлением дерева.Затем я надеюсь загрузить различные текстовые файлы, выбранные пользователем, интерпретируя, какие флажки были истинными или ложными. Все кажется довольно простым, кроме перебора словаря без фиксации глубины.

Говоря более абстрактно

Для создания этих вложенных словарей я использую рецепт ActiveState - http://code.activestate.com/recipes/577879/ . Он реализует os.walk для создания таких словарей:

a={
    'SomeRootDirectory': {
        'foo.txt': None,
        'bar.txt': None,
        'Stories': {
            'Horror': {
                'horror.txt' : None,
                'Trash' : {
                    'notscary.txt' : None,
                    },
                },
            'Cyberpunk' : None
            },
        'Poems' : {
            'doyoureadme.txt' : None
        }
    }
}

После этого я в тупике. Я новичок в Python на момент написания

Решение, адаптированное на основе ответа 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

Это дает то, что, я думаю, будет очень легко преобразовать в представление Tkinter:

SomeRootDirectory
/===Poems
|---|---doyoureadme.txt
/===Stories
/===/===Horror
|---|---|---rickscott.txt
/===/===/===Trash
|---|---|---|---notscary.txt
/===/===Cyberpunk
|---foo.txt
|---bar.txt

Спасибо, это сообщество невероятно.

7
задан driftcatcher 4 April 2018 в 20:22
поделиться