2026, Jan 10 21:05

Централизация расширений медиафайлов: Python‑модуль и YAML

Разбираем два способа хранить расширения медиафайлов в Python: общий модуль с кортежами и YAML‑конфигурацию с помощником. Меньше дублирования, проще поддержка.

Когда несколько Python-скриптов просматривают текущую рабочую директорию в поисках медиафайлов, жестко прописывать десятки расширений в каждом скрипте быстро превращается в проблему сопровождения. Как только появляется новый тип, приходится копировать правки по разным файлам. Логичное улучшение — централизовать эти сведения в одном месте. Ниже — практический разбор двух подходов и того, как аккуратно их подключить.

Базовый вариант: общий Python‑модуль с кортежами расширений

Часто начинают с отдельного модуля, в котором хранятся списки типов файлов, а каждый скрипт его импортирует. Структура проста: небольшой конфигурационный файл с кортежами расширений и скрипт, который находит модуль, загружает его и фильтрует файлы в текущей директории.

C:\code\script1.py
C:\code\SYS_python\media_file_types.py

(base) P:\aaa\bbb\CWD> python c:\code\script1.py

Пример конфигурационного модуля:

# C:\code\SYS_python\media_file_types.py
pic_kinds = ('jpg', 'jpeg', 'jfif', 'gif')
clip_kinds = ('mov', 'lrv', 'thm', 'xml')
sound_kinds = ('3gpp', 'aiff', 'pcm', 'aac')

Пример импорта и использования в скрипте (пути сохранены, имена изменены, поведение то же):

import os
import sys

cfg_path = os.path.join(os.path.dirname(__file__), 'SYS_python')
cfg_file = os.path.join(cfg_path, 'media_file_types.py')

if not os.path.exists(cfg_file):
    print(f"Error: Config file '{cfg_file}' is missing.")
    sys.exit(1)
else:
    sys.path.append(cfg_path)
    try:
        import media_file_types as media_defs

        pic_exts = tuple(f".{e.lower()}" for e in media_defs.pic_kinds)
        clip_exts = tuple(f".{e.lower()}" for e in media_defs.clip_kinds)
        sound_exts = tuple(f".{e.lower()}" for e in media_defs.sound_kinds)
        all_exts = pic_exts + clip_exts + sound_exts

        pic_list = [n for n in os.listdir('.') if n.lower().endswith(pic_exts)]
        clip_list = [n for n in os.listdir('.') if n.lower().endswith(clip_exts)]
        sound_list = [n for n in os.listdir('.') if n.lower().endswith(sound_exts)]

        print(f"Found {len(pic_list)} photo files.")
        print(f"Found {len(clip_list)} video files.")
        print(f"Found {len(sound_list)} audio files.")

    except ImportError:
        print(f"Error: Unable to import 'media_file_types' from '{cfg_path}'.")
        sys.exit(1)
    except AttributeError as exc:
        print(f"Error: Expected attributes missing in 'media_file_types': {exc}")
        sys.exit(1)

Что здесь происходит и почему это работает

Конфигурация живет в отдельном модуле, где расширения перечислены кортежами. Скрипт формирует путь к каталогу с модулем, проверяет, что файл существует, дополняет sys.path, импортирует модуль, нормализует расширения к нижнему регистру с точкой впереди и собирает файлы, проверяя endswith для соответствующего кортежа. Он также выводит счетчики и завершает работу заранее, если конфигурация отсутствует или в ней нет ожидаемых атрибутов. Результат — единый источник истины для всех скриптов, которым нужна одна и та же таксономия медиа.

Альтернатива: конфигурация YAML и небольшой вспомогательный класс

Тот же «единый источник истины» можно оформить в виде файла .yaml. Определения выносятся из кода Python в простой документ с данными, а скрипты обращаются к вспомогательному классу за нужными расширениями и затем сканируют директории.

Пример структуры YAML:

media_types:
  photo:
    - jpg
    ...
  video:
    ...

Пример вспомогательного класса и его использования (имена изменены, поведение сохранено):

import os
from pathlib import Path

class MediaRegistry:
    def gather_ext(self, kind, include_dot=True):
        exts = self.media_types.get(kind.lower(), [])
        if include_dot:
            return tuple(f".{x.lower()}" for x in exts)
        return tuple(x.lower() for x in exts)

    def collect_files(self, root='.', kind=None):
        exts = self.gather_ext(kind)
        return [p for p in os.listdir(root) if p.lower().endswith(exts)]

manifest_path = Path(__file__).parent / 'SYS_python' / 'media_config.yaml'
registry = MediaRegistry()  # требуется инициализация
files_photo = registry.collect_files(kind='photo')

Определения хранятся в одном YAML‑файле. Класс предоставляет две точечные операции: вернуть расширения для запрошенного типа медиа — с ведущей точкой или без нее — и просканировать каталог, используя эти расширения. Путь к YAML располагается рядом со скриптами, и вы инициализируете класс соответствующим образом.

Почему это стоит знать

Оба подхода консолидируют знания о типах медиа, так что вы редактируете один файл вместо множества скриптов. В первом случае используется Python‑модуль с кортежами и явными проверками импорта. Во втором — тот же замысел, но через файл данных и тонкий слой, предоставляющий методы «получить и найти». В любом варианте вы избавляетесь от дублирования и упрощаете добавление новых расширений сразу во всех точках входа.

Практический вывод

Если у вас уже есть общие модули для скриптов, хранить кортежи в выделенном модуле и импортировать их с базовой валидацией — рабочее и простое решение. Если предпочитаете источник только с данными, к которому скрипты обращаются через небольшой помощник, разместите списки в .yaml и читайте их через класс — получите ту же централизацию. Используйте один конфигурационный файл, один раз нормализуйте расширения, и пусть все скрипты используют общее определение вместо того, чтобы переопределять его.