2025, Oct 16 07:16
Как исправить AttributeError: нет igl.tet_tet_adjacency
AttributeError в libigl: нет igl.tet_tet_adjacency при запуске fracture-modes. Причина — изменения биндингов. Решение: откат до igl 2.2.0. Без правок кода.
Запускаешь старый исследовательский скрипт — и внезапно вылетает AttributeError: module 'igl' has no attribute 'tet_tet_adjacency — легко потерять терпение. Этот конкретный сбой проявляется при запуске примера fracture-modes: шаг «взрыва» сетки опирается на Python‑биндинги libigl. Раньше код работал, но в более новой среде нужный атрибут исчез. Источник поломки — изменения в биндингах libigl, а не ошибка в самом скрипте.
Как воспроизвести ошибку
Ошибка появляется в момент, когда из libigl запрашивается тетраэдральная смежность. Цепочка вызовов упирается в одну строку вроде этой, которая вычисляет смежность для тетраэдральной сетки.
import igl
def make_exploded_mesh(pts, cells):
    neigh, neigh_ids = igl.tet_tet_adjacency(cells)
    return neigh, neigh_ids
# Где-то выше по коду функция вызывается с индексами тетраэдров
# make_exploded_mesh(vertices, tetrahedra)
В средах, где биндинги больше не предоставляют tet_tet_adjacency, импорт igl проходит успешно, но вызов igl.tet_tet_adjacency приводит к AttributeError. Пользователи сообщали об этом на версии libigl 2.6.1.
Что на самом деле происходит
Проблема связана с Python‑биндингами libigl, а не с кодом геометрии в репозитории. Репозиторий был создан несколько лет назад и не фиксирует конкретную версию igl, поэтому при установке или обновлении зависимостей можно незаметно получить более свежие биндинги, где tet_tet_adjacency больше не доступна под тем же именем или в том же месте. Поскольку скрипт опирается на этот символ буквально в таком виде, поиск атрибута падает уже во время выполнения.
Рабочее решение прямо сейчас
Самый быстрый путь — откатить пакет igl к релизу, в котором эта функция есть. Подтвержденный рабочий вариант — igl==2.2.0. Зафиксировав эту версию, вы вернете исходное поведение без каких‑либо изменений в коде проекта.
# requirements.txt
igl==2.2.0
После фиксации версии переустановите зависимости и снова запустите пример. Тот же вызов igl.tet_tet_adjacency в Python должен пройти успешно, и вычисление режима разрушения продолжится как раньше.
Если нужна более надежная настройка
Более обстоятельный, хотя и затратный по времени путь — просмотреть журнал изменений libigl и связанные issues или PR, чтобы понять, была ли функция удалена, переименована или перемещена в биндингах, а затем зафиксировать именно совместимую версию для этого проекта. Это убережет от поломок при разворачивании новых окружений и выровняет ожидания для всех, кто будет запускать код.
Почему это важно
Инструменты для науки и графики часто опираются на нативные библиотеки с Python‑биндингами, а эти биндинги со временем меняются. В старых репозиториях, где версии зависимостей не закреплены, одно обновление может удалить или переименовать API и сломать критические пути во время выполнения. Понимание того, что сбой вызван движущейся зависимостью, а не логикой проекта, позволяет сосредоточиться на контроле окружения, а не на рефакторинге алгоритма.
Итоги и практические советы
Если при запуске примера fracture-modes вы сталкиваетесь с AttributeError на igl.tet_tet_adjacency, рассматривайте это как несоответствие биндингов. Откатите igl к более раннему релизу, где функция присутствует; сообщается, что igl==2.2.0 устраняет проблему. Код менять не нужно — просто зафиксируйте версию зависимости, чтобы стабилизировать окружение. Для долгосрочной надежности изучите релиз‑ноты libigl и закрепите требуемую версию в конфигурации проекта, чтобы новые установки воспроизводили то же поведение без сюрпризов.
Статья основана на вопросе с StackOverflow от albusdemens и ответе от Kirill Ilichev.