Sphinx autodoc 不显示所有类型或循环导入错误

Sphinx autodoc does not display all types or circular import error

我正在尝试使用 sphinx autodoc、napoleon 和 autodoc_typehints 自动生成文档类型,但我遇到了问题,因为它不适用于我的大多数类型。我正在使用 deap 包来做一些遗传优化算法,这使得我有一些我猜 sphinx 无法处理的非常具体的类型。

我的 conf.py 文件如下所示:

import os
import sys
sys.path.insert(0, os.path.abspath('../python'))

extensions = [
    'sphinx.ext.autodoc',
    'sphinx.ext.viewcode',
    'sphinx.ext.napoleon',
    'sphinx_autodoc_typehints'
]


set_type_checking_flag = False
always_document_param_types = False

我有一个 Algo.rst 文件:

.. automodule:: python.algo.algo
     :members: crossover_worker,
               test

和我的 python.algo.algo 模块看起来像这样(我添加了一个虚拟测试函数以显示它在我没有指定特殊类型时工作):

# Type hinting imports
from config.config import Config
from typing import List, Set, Dict, NamedTuple, Union, Tuple
from types import ModuleType
from numpy import ndarray
from numpy import float64
from multiprocessing.pool import MapResult
from deap.tools.support import Logbook, ParetoFront
from deap.base import Toolbox
from pandas.core.frame import DataFrame
from deap import creator

...

def crossover_worker(sindices: List[creator.Individual, creator.Individual]) -> Tuple[creator.Individual, creator.Individual]:
    """
    Uniform crossover using fixed threshold

    Args:
        sindices: list of two individuals on which we want to perform crossover

    Returns:
        tuple of the two individuals with crossover applied
    """
    ind1, ind2 = sindices
    size = len(ind1)
    for i in range(size):
        if random.random() < 0.4:
            ind1[i], ind2[i] = ind2[i], ind1[i]
    return ind1, ind2


def test(a: DataFrame, b: List[int]) -> float:
    """
    test funcition

    Args:
        a: something
        b: something

    Returns:
        something
    """
    return b

conf.py 中的设置像上面一样时,我没有错误,我的 test 函数的类型是正确的,但是我的 crossover_worker 函数的类型丢失了:

但是,当我将 set_type_checking_flag= True 设置为强制使用所有类型时,出现循环导入错误:

reading sources... [100%] index
WARNING: autodoc: failed to import module 'algo' from module 'python.algo'; the following exception was raised:
cannot import name 'ArrayLike' from partially initialized module 'pandas._typing' (most likely due to a circular import) (/usr/local/lib/python3.8/site-packages/pandas/_typing.py)
looking for now-outdated files... none found

而且我从不导入 ArrayLike 所以我不知道它来自哪里或如何解决它? 或者如何强制导入在我的代码中随处可见的 creator.Individual 类型?

我的狮身人面像版本:

sphinx==3.0.1
sphinx-autodoc-typehints==1.10.3

经过一番搜索,我的方法存在一些缺陷:

  • 首先是"list is a homogeneous structure containing values of one type. As such, List only takes a single type, and every element of that list has to have that type." ()。因此,我不能做类似 List[creator.Individual, creator.Individual] 的事情,但应该将其转换为 List[creator.Individual] 或者如果列表中有多个类型,则应该使用联合运算符,例如 List[Union[int,float]]
  • 其次,creator.Individual 类型未被 sphinx 识别为有效类型。相反,我应该使用 TypeVar 定义它:
from typing import TypeVar, List
CreatorIndividual = TypeVar("CreatorIndividual", bound=List[int])

因此,通过将我的 crossover_worker 函数转换成这个,一切都奏效了:

def crossover_worker(sindices: List[CreatorIndividual]) -> Tuple[CreatorIndividual, CreatorIndividual]:

注:"By contrast, a tuple is an example of a product type, a type consisting of a fixed set of types, and whose values are a collection of values, one from each type in the product type. Tuple[int,int,int], Tuple[str,int] and Tuple[int,str] are all distinct types, distinguished both by the number of types in the product and the order in which they appear."()