You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用MkDocstrings生成Markdown文件时,如何在子文件夹无__init__.py的情况下解决构建错误

使用MkDocstrings生成Markdown文件时,如何在子文件夹无__init__.py的情况下解决构建错误

我完全理解你的困扰——看着自己的项目里wrkpkg1、wrkpkg2这类不需要作为Python包的子目录,为了生成文档被迫加一堆没用的__init__.py,确实破坏了原本的结构。结合你给出的项目结构和错误信息,下面给你几个可行的解决方案:

方案1:调整gen_ref_pages.py脚本,适配无__init__.py的目录

你当前用的gen_ref_pages.py(通常是mkdocs-gen-files的默认脚本)可能依赖pkgutil.iter_modules来遍历包,这个方法会跳过没有__init__.py的目录。我们可以修改脚本,直接用文件系统遍历所有.py文件,然后把路径转换为模块名:

import os
from pathlib import Path
import mkdocs_gen_files

# 指向你的packages目录,根据实际路径调整
root = Path(__file__).parent.parent / "packages"
nav = mkdocs_gen_files.Nav()

# 遍历所有.py文件
for path in sorted(root.rglob("*.py")):
    # 跳过缓存目录和已有的__init__.py
    if "__pycache__" in str(path) or path.name == "__init__.py":
        continue
    
    # 将文件路径转换为模块标识:packages/pkg1/subpkg1/wrkpkg1/file1.py → packages.pkg1.subpkg1.wrkpkg1.file1
    module_path = path.relative_to(root).with_suffix("")
    doc_path = path.relative_to(root).with_suffix(".md")
    full_doc_path = Path("reference", doc_path)
    
    # 更新导航结构
    parts = tuple(module_path.parts)
    nav[parts] = doc_path.as_posix()
    
    # 生成对应的文档引用文件
    with mkdocs_gen_files.open(full_doc_path, "w") as fd:
        ident = ".".join(parts)
        fd.write(f"::: {ident}")
    
    # 设置编辑路径关联
    mkdocs_gen_files.set_edit_path(full_doc_path, path)

# 生成导航汇总文件
with mkdocs_gen_files.open("reference/summary.md", "w") as fd:
    fd.writelines(nav.build_literate_nav())

这个脚本会无视目录是否有__init__.py,直接遍历所有Python文件并生成对应的文档页面。

方案2:配置mkdocstrings的Griffe解析器,支持命名空间包

MkDocstrings依赖Griffe工具收集代码信息,Griffe本身支持识别Python 3.3+引入的命名空间包(无__init__.py的目录)。你可以在mkdocs.yaml中添加Griffe的相关配置:

mkdocstrings:
  default_handler: python
  handlers:
    python:
      griffe:
        # 启用嵌套模块识别,即使父目录无__init__.py
        find_nested_modules: true
        # 将无__init__.py的目录视为命名空间包的一部分
        recognize_nested_packages: true
      options:
        # 开启子模块文档展示
        show_submodules: true

配置完成后,配合方案1的脚本,就能正常收集无__init__.py目录下的模块信息了。

方案3:临时生成空__init__.py(折中方案)

如果上面的方案暂时无法生效,你可以用脚本临时生成空的__init__.py,构建完成后再删除,既不破坏原有结构,又能满足文档生成的要求:

import os
from pathlib import Path
import subprocess

root = Path("packages")
temp_init_files = []

# 生成临时__init__.py
for path in root.rglob("*/"):
    init_path = path / "__init__.py"
    if not init_path.exists():
        init_path.touch()
        temp_init_files.append(init_path)

# 执行mkdocs构建
subprocess.run(["mkdocs", "build"], check=True)

# 清理临时生成的__init__.py
for init_file in temp_init_files:
    init_file.unlink()

这个方法属于应急折中,适合快速验证,但不如前两个方案优雅。

最后记得重启mkdocs服务或重新执行mkdocs build,确保配置和脚本的修改生效。

备注:内容来源于stack exchange,提问作者aniruddha das

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 16:34:50