Sphinx和Python中的相对导入3. *

时间:2013-11-27 19:07:32

标签: python python-3.x python-sphinx

我有一个带有python包的目录,如下所示:

--docs/index.rst
--docs/...
--app/__init__.py
--app/foo.py

我正在使用带有autodocs的sphinx来记录应用程序(在python 3.3中)。

现在,在conf.py(内部docs/)中,我有

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

cd进入docs/,运行

make html

给了我

SystemError:未加载父模块,无法执行相对导入

到具有

的所有模块
from .foo import Bar

我使用

安装了Sphinx的干净virtualenv
pip install Sphinx

为python 3.3创建(干净)环境后。

我错过了什么?

我正在将项目从python 2. *移动到python 3. *当发生这种情况时。所有项目都在运作,但是......

1 个答案:

答案 0 :(得分:14)

您的app目录是一个包。包是一个包含__init.py__的目录,其中包含其他文件。

如果您在sys.path上放置了一个包目录,那么各种各样的事情都会出错。

我们举一个例子:

root/
    app/
        app/__init__.py
        app/spam.py
        app/eggs.py

如果root上有sys.path(因为它是您当前的工作目录,或者是因为您明确地这样做了,或者因为您已正确安装了site-packages),然后app是一个包,app.spam是一个模块,在app.eggs中,.spam是该模块。一切顺利。

如果app上有sys.path,那么app不是一个包,spam是一个模块,并且在eggs.spam 1}}不是什么。所以,你不能使用相对导入。

如果sys.path上有两者,那么app是一个包,spamapp.spam都是不同的模块(使用相同的内容,执行两次),并且在app.eggs内,.spam是一个模块,但在eggs内,.spam不是任何内容。这将导致你无法解决问题。


所以,最有可能的是,您想要的修复是这样的:

sys.path.insert(0, os.path.abspath('..'))

如果有其他软件包或者不是软件包的Python代码的目录,则..中您不想自动分区(例如,tests目录{{1}然后你需要重新构建你的目录,把tests/test_spam.py放到一个没有任何其他Python代码的目录中,如下所示:

app

或者,如果您不希望root/ src/ app/ tests/ doc/ 成为一个包,而是希望成为一个sys.path根目录,那么请终止app,并将__init__.py直接保留在app。但在这种情况下,你不能使用包内相对进口; sys.path中的所有模块都是顶级模块,必须按原样导入。


本教程的Packages部分(以及上面章节的其余部分)解释了其中的一些内容,但可能有更好的介绍性文档。

有关详细信息,请参阅3.3+,The import system包含所有内容,组织良好;对于旧版本,参考文档是泥泞,不完整和分散的;你必须从The import statement开始,然后阅读The Knights Who Say Neeeow ... Wum ... Ping!(这基本上是一个PEP但1.5还没有PEP),甚至可能是app文档,如果你能找到的话它,以及各种PEP和次要变更日志条目,解释事情在1.5和2.7或3.2或其他任何事情之间的变化。