现象
pyproject.toml 声明的依赖和代码里真正 import 的东西对不上:有的硬依赖从来没被 import,有的模块级硬 import 却根本没声明。目前之所以没炸,是靠传递依赖碰巧补上了。
证据
包
声明位置
实际 import
问题
matplotlib
只在 [dependency-groups] dev
abses/utils/func.py 模块级 from matplotlib import pyplot as plt
事实上的运行时依赖,未声明
seaborn
[project.dependencies]
全仓零 import (grep -rn "seaborn|sns\." abses/ 无结果)
硬依赖,唯一作用是间接把 matplotlib 装进来
solara
完全未声明
abses/viz/solara.py 模块级 import solara
干净环境下 tests/viz/test_solara.py 必崩
networkx
完全未声明
abses/human/links.py 用 contextlib.suppress(ImportError) 包住 import,但后面无条件使用 nx
缺失时报 NameError: name 'nx' is not defined,无法诊断
fontawesome / icons
[project.dependencies]
只被死模块 abses/viz/customize_marker.py 使用(零 import、0% 覆盖)
为死代码背两个硬依赖
matplotlib 确实在 import abses 的主路径上:
abses/__init__.py → space/nature.py → space/patch.py → abses/utils/func.py:29 (from matplotlib import pyplot as plt)
utils/func.py 里唯一用到 plt 的是 with_axes 装饰器,而 with_axes 在 abses/ 内部零使用、tests/ 内部零使用——也就是说主路径上这个 import 完全是为了一个没人用的装饰器。
同一主题:tracker 的 ImportError 守卫不可达
abses/utils/tracker/factory.py:
elif backend == "aim" :
try :
from abses .utils .tracker .aim_tracker import AimTracker
except ImportError as exc :
raise ConfigurationError ("Aim tracker selected but aim is not installed. ..." ) from exc
tracker = AimTracker (cfg_dict .get ("aim" , {})) # ← 在 try 之外
aim_tracker.py 自己已经吞掉了 ImportError(except ImportError: Run = None),所以这个模块永远能干净导入 ,except ImportError 分支不可达。真正的 ImportError 由 AimTracker.__init__ 抛出,绕过了这句友好的 ConfigurationError 直接冒泡给用户。mlflow 分支同样。
修法:把构造调用挪进 try 里。
建议方案
把 matplotlib 加进 [project.dependencies];或者把 with_axes 从 utils/func.py 挪到 abses/viz/,让 matplotlib 彻底离开核心 import 路径(更干净,且能让 import abses 变快)。
移除 seaborn(无人使用)。
新增 [project.optional-dependencies].viz,包含 solara + matplotlib,并把 abses/viz/solara.py 的 import 做成延迟/带守卫的。
显式声明 networkx(links.py 无条件使用),或把使用点也真正做成可选。
删除 abses/viz/customize_marker.py 并移除 fontawesome / icons——注意这是公共命名空间的移除,见 wheel 未打包 data/,load_data() 对 pip 安装用户不可用 #154 。
修正 factory.py 里两处不可达的 except ImportError。
验收标准
现象
pyproject.toml声明的依赖和代码里真正 import 的东西对不上:有的硬依赖从来没被 import,有的模块级硬 import 却根本没声明。目前之所以没炸,是靠传递依赖碰巧补上了。证据
matplotlib[dependency-groups] devabses/utils/func.py模块级from matplotlib import pyplot as pltseaborn[project.dependencies]grep -rn "seaborn|sns\." abses/无结果)solaraabses/viz/solara.py模块级import solaratests/viz/test_solara.py必崩networkxabses/human/links.py用contextlib.suppress(ImportError)包住 import,但后面无条件使用nxNameError: name 'nx' is not defined,无法诊断fontawesome/icons[project.dependencies]abses/viz/customize_marker.py使用(零 import、0% 覆盖)matplotlib确实在import abses的主路径上:utils/func.py里唯一用到plt的是with_axes装饰器,而with_axes在abses/内部零使用、tests/内部零使用——也就是说主路径上这个 import 完全是为了一个没人用的装饰器。同一主题:tracker 的 ImportError 守卫不可达
abses/utils/tracker/factory.py:aim_tracker.py自己已经吞掉了ImportError(except ImportError: Run = None),所以这个模块永远能干净导入,except ImportError分支不可达。真正的ImportError由AimTracker.__init__抛出,绕过了这句友好的ConfigurationError直接冒泡给用户。mlflow 分支同样。修法:把构造调用挪进
try里。建议方案
matplotlib加进[project.dependencies];或者把with_axes从utils/func.py挪到abses/viz/,让 matplotlib 彻底离开核心 import 路径(更干净,且能让import abses变快)。seaborn(无人使用)。[project.optional-dependencies].viz,包含solara+matplotlib,并把abses/viz/solara.py的 import 做成延迟/带守卫的。networkx(links.py无条件使用),或把使用点也真正做成可选。abses/viz/customize_marker.py并移除fontawesome/icons——注意这是公共命名空间的移除,见 wheel 未打包 data/,load_data() 对 pip 安装用户不可用 #154。factory.py里两处不可达的except ImportError。验收标准
[project.dependencies]的干净环境里,import abses成功,且python -c "from abses import MainModel, Actor; MainModel()"能跑通。ConfigurationError而不是裸ImportError。pyproject.toml里不再有零 import 的依赖。