使用Sphinx自动文档时遇“Attempted relative import”错误求助
这个问题的核心是相对导入的作用范围和Sphinx的模块导入逻辑不匹配,我们来一步步拆解原因和解决办法:
问题根源
你的fileInfo.py里用了相对导入from ..utils.folder import get_files_directory,这里的..是要回到pre_processing的父目录(也就是src),再找到utils子目录。但Sphinx在导入模块时,是把../../../src/加到了sys.path里,这时候Python会把src目录下的pre_processing和utils都当成顶级包,而不是某个父包的子包。当你导入pre_processing.fileInfo时,pre_processing就成了顶级包,..试图跳出这个顶级包自然就会报错。
解决方案
方案1:把src目录转为可安装的Python包(推荐)
这是最规范的做法,能从根本上解决导入问题,同时也方便项目的其他开发和测试:
- 在
src目录下创建__init__.py(可以是空文件),让src成为一个Python包 - 在
pre_processing和utils目录下也分别创建__init__.py(同样可以是空文件),把它们变成src的子包 - 回到项目根目录,执行
pip install -e .(以可编辑模式安装包),这样Python会把整个项目识别为一个包结构 - 修改Sphinx的
conf.py里的sys.path设置为:import os import sys sys.path.insert(0, os.path.abspath('../../../')) # 指向项目根目录而不是src - 之后在Sphinx的文档里,你可以用
autodoc导入src.pre_processing.fileInfo,相对导入就能正常工作了
方案2:改用绝对导入
如果你暂时不想把项目做成可安装包,可以修改fileInfo.py里的导入语句为绝对导入:
from utils.folder import get_files_directory
同时确保conf.py里的sys.path指向src目录(也就是你现在的设置),这样Python能直接在sys.path里找到utils包,避免相对导入的问题。不过这种方式不够规范,当项目结构变动时容易出问题。
方案3:调整Sphinx的模块导入方式
在conf.py里,你可以尝试直接添加项目根目录到sys.path,然后用完整的包路径导入模块:
import os import sys sys.path.insert(0, os.path.abspath('../../../')) # 指向项目根目录
然后在你的.rst文档里,使用autodoc时指定完整的模块路径:
.. automodule:: src.pre_processing.fileInfo :members:
这样Sphinx会从项目根目录开始识别包结构,相对导入的..utils就能正确找到对应的模块了。
提示:不管用哪种方案,修改完配置后记得清空Sphinx的
build目录,重新生成文档,避免缓存导致的问题。
内容的提问来源于stack exchange,提问作者floriandaniel

