2025, Oct 31 08:47

Как сгенерировать index.html во всех папках статического сайта на Python

Показываем, как одной функцией на Python и os.walk генерировать index.html в каждой папке статического сайта без хардкода путей и лишних скриптов. Пример кода.

Сгенерировать index.html для каждой папки статического сайта кажется простой задачей, но на деле она нередко превращается в клубок захардкоженных путей, ручной рекурсии и неожиданных FileNotFoundError. Если ваш скрипт постоянно «теряет» текущую директорию или требует index.py в каждой папке, вы боретесь с файловой системой вместо того, чтобы спокойно обходить её. Есть более аккуратный подход.

Что идет не так в наивном подходе

Частая схема: навести скрипт на одну папку, сгенерировать там index.html, а затем запустить дополнительные скрипты для вложенных каталогов. Это быстро приводит к хрупкой работе с путями и дублированию логики. Ниже — упрощённый вариант такого подхода, показывающий, почему пути «плывут» и почему приходится прибегать к жёстко прописанным значениям.

from pathlib import Path
def build_listing_html(base_loc):
    base_loc = Path(base_loc)
    base_loc = base_loc / 'FOLDER A'
    with open(base_loc / 'index.html', 'w') as fp:
        for entry in sorted(list(base_loc.iterdir())):
            fp.write(f'<a href="{entry.name}">{entry.name}</a>\n')
if __name__ == '__main__':
    build_listing_html('.')
with open("./FOLDER A/SUBFOLDER B/index.py") as fh:
    exec(fh.read())

Этот код насильно переключает процесс в конкретный подкаталог, а затем выполняет другой скрипт для ещё более глубокого уровня. Когда всё запускается из корня проекта, относительные пути указывают не туда, если только вы не прописываете абсолютные расположения вручную. Отсюда и FileNotFoundError, а также ощущение, что без index.py в каждой папке не обойтись.

Суть проблемы

Обход файловой системы выполняется вручную и разрозненно. Каждый шаг рассчитывает на определённую рабочую директорию и опирается на строковые пути. Стоит контексту выполнения сместиться — относительные ссылки ломаются. В итоге появляются лишние точки входа и копии скриптов в разных папках.

Проще: один проход по дереву с генерацией индексных файлов на ходу

Вместо прыжков между директориями и запуска множества скриптов, пройдите всё дерево каталогов за один раз и в ходе этого прохода создавайте index.html в каждой папке. os.walk() на каждой итерации явно сообщает, в какой директории вы находитесь, избавляя от самодельных манипуляций с путями. Нужно скрыть отдельные файлы из списка — отфильтруйте их перед записью. Нужна более выразительная разметка — подключите шаблонизатор вроде jinja, но сам обход останется неизменным.

import os
def emit_indexes(site_root):
    index_name = "index.html"
    ignore_set = {index_name, "some_other_file.py"}
    link_tpl = '<a href="{filename}">{filename}</a>'
    for dir_here, subdirs, files_here in os.walk(site_root):
        index_path = os.path.join(dir_here, index_name)
        files_here = [x for x in files_here if x not in ignore_set]
        with open(index_path, "w") as outf:
            for fname in files_here:
                outf.write(link_tpl.format(filename=fname) + "\n")
SITE_BASE = "D:/temp/StackOverflow/foo"
emit_indexes(SITE_BASE)

Такой подход создаёт index.html в каждой найденной директории. Он также избегает самоссылок, исключая имя выходного файла из списка, и при необходимости позволяет добавить другие элементы для игнорирования. Процесс самодостаточен и не требует отдельного index.py в каждой папке.

Почему это важно

Один проход по дереву устраняет путаницу с путями и делает сбои предсказуемыми. Вам больше не нужно жёстко прописывать местоположения, вы сокращаете дублирование скриптов и сохраняете предсказуемость относительных href. Подход естественно масштабируется при изменении структуры: новые подкаталоги автоматически получают свой index.html без дополнительной настройки.

Практическое резюме

Пусть логику диктует сама файловая система. Пройдите дерево один раз, создавайте индекс для каждой посещённой директории и отбрасывайте файлы, которые не хотите показывать. Требуется более богатая разметка — подключите шаблонизатор вроде jinja. Если что-то кажется странным, во время обхода выводите текущую директорию и путь к файлу, чтобы понять, куда именно пишет скрипт. С такой структурой можно перестать микроменеджить пути и позволить вашему статическому сайту индексировать себя сам.

Статья основана на вопросе с StackOverflow, автор — chungusG, и на ответе JonSG.