Символьные ссылки, как средство повторного использования кода при разработке аддонов Blender

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

Использование символических ссылок при разработке аддонов
Использование символьных ссылок при разработке аддонов

Python, в соответствии с правилами импорта пакетов, предоставляет возможность подключать модули следующими способами:

  1. Прямым импортированием, если модуль расположен внутри текущего пакета.

Для того, чтобы модуль присутствовал в пакете, его нужно туда скопировать. Это самый простой и в тоже время самый неоптимальный вариант. Дублирование кода, которого всегда следует избегать, здесь максимально. В случае, если в скопированном модуле обнаружится ошибка, для исправления нужно отследить все сделанные копии. Если в одном аддоне модуль будет чем-либо усовершенствован — добавлен новый класс или метод, изменения опять же коснуться только текущей копии, и чтобы внести их во все остальные копии модуля, нужно будет приложить немало сил.

  1. Если модуль располагается за пределами пакета, его все равно можно импортировать, добавив путь к директории модуля в переменную окружения sys.path.

Таким образом импортируются модули в запускающий скрипт Blender для отладки многомодульных аддонов. Этот вариант лишен основного недостатка первого, но и у него есть свои минусы. Модуль хранится в отдельном месте в единственном экземпляре, все правки и дополнения затрагивают только его и автоматически становятся доступны во всех остальных аддонах, в которые модуль был импортирован. Проблем с дублированием кода нет. Однако в этом случае при создании релиза аддона, необходимо пройтись по всем подключенным таким образом модулям и скопировать их все в распространяемый пакет.

  1. Создать в пакете аддона символьную ссылку на необходимый модуль, чтобы обращаться к модулю через нее.

Самый удобный вариант, который лишен вышеперечисленных минусов. Python корректно работает с символьными ссылками и в Windows и в Linux. Дублирования кода нет — через символьную ссылку все правки и дополнения вносятся сразу в исходный модуль, никаких реальных копий не создается. В то же время при упаковке пакета в архив для создания распространяемого релиза, архиваторы корректно упаковывают не ссылку на модуль, а помещают в архив копию самого модуля.

Возьмем для примера простейший универсальный класс для работы с двухмерным вектором:

Его можно использовать во множестве аддонов, поэтому сохраним его в отдельный модуль Vector2d.py в директории d:\Python\Vector2d\.

Создадим отдельный аддон SampleProject, единственной задачей которого будет демонстрация подключения и использования модуля Vector2d.

  1.  Создать директорию d:\Python\SampleProject\
  2. Создать в ней файл __init__.py
Пример аддона SampleProject
Пример аддона SampleProject

Для того, чтобы подключить к аддону ранее созданный модуль Vectro2d, создадим в директории SampleProject символьную ссылку на этот модуль.

В операционной системе Windows символьные ссылки создаются командой mklink (для Linux — систем нужно использовать команду ln) или с помощью файловых менеджеров, умеющих работать с символьными ссылками (таких как Far). Важное замечание — в операционной системе Windows символьные ссылки поддерживаются начиная с версии Vista. Пользователям старших систем придется использовать 1 или 2 метод работы с модулями.

Создадим командный файл link.cmd со следующей командой:

После выполнения этого файла, в директории d:\Python\SampleProject будет создана символьная ссылка Vector2d.py, указывающая на модуль d:\Python\Vector2d\Vector2d.py.

Символьная ссылка на модуль Vector2d.py
Символьная ссылка на модуль Vector2d.py

Для проверки работы в файл __init__.py занесем универсальный код для многомодульных аддонов с небольшими изменениями. В первую очередь в список подключаемых модулей внесем Vector2d.

В функцию register добавим несколько дополнительных строчек кода. Так как эта функция вызывается в момент активации аддона, добавленный код будет сразу же выполнен.

Напомню, что это плохая практика, в реальном аддоне никакого дополнительного кода в __init__.py быть не должно. Данный код добавляется исключительно для демонстрации, что при использовании символьных ссылок «все работает». Здесь создаются два вектора v1 и v2 и выводятся результат простейшего действия (сложения) с этими векторами.

Итоговое содержание файла __init__.py:

Для проверки работы, в отладочном скрипте Blender укажем директорию аддона:

и запустим его нажатием на кнопку Run Script. Открыв консольное окно System Console, можно увидеть результат сложения двух векторов.

Результат работы
Результат работы

Протестировав подключение модуля через символьную ссылку в режиме отладки, попробуем собрать релизный пакет. Для этого директорию d:\Python\SampleProject\ упакуем архиватором zip в архив. Если после этого открыть архив, можно заметить, что файл Vector2d.py упаковался не как символьная ссылка (размер 0 байт), а как реальный файл (размер 568 байт).

Заархивированная *.zip релизная версия аддона (справа)
Заархивированная *.zip релизная версия аддона (справа)

Проведем установку аддона из полученного архива.

Установка и активация аддона
Установка и активация аддона

После активации аддона в консоли System Console выведены результаты сложения векторов, что означает, что аддон корректно установлен и работает без ошибок.