【问题标题】:Python3 correct way to import relative or absolute?Python3导入相对或绝对的正确方法?
【发布时间】:2015-04-08 15:45:27
【问题描述】:

我正在编写一个 python 模块 neuralnet。它在 Python2 中一切正常,但在 Python3 中导入失败。

这是我的代码结构。

neuralnet/
    __init__.py
    train.py         # A wrapper to train (does not define new things)
    neuralnet.py     # Defines the workhorse class neuralnet
    layer/
        __init__.py
        inlayer.py       # Defines input layer class
        hiddenlayer.py

application/         # A seperate application (not part of the package)
   classify.py       # Imports the neuralnet class from neuralnet.py

train.py需要导入neuralnet.py的neuralnet类。

neuralnet.py需要导入layers/inlayer.py

(我更喜欢相对导入。)

我有一个不同的应用程序 (classify.py) 需要导入这个模块。 我在哪里...

from neuralnet.neuralnet import neuralnet

我尝试了几种导入方式。 要么我得到一个错误(主要是像父母一样神秘的没有导入)

  1. 在运行 train.py(这是神经网络模块的一部分)时

    from . import layer  # In file neuralnet.py
    SystemError: Parent module '' not loaded, cannot perform relative import
    

或者

  1. 同时运行classify.py(在模块之外)。

    from layer.inlayers import input_layer   # In file neuralnet.py
    ImportError: No module named 'layer'
    

多年来,我的导入在 Python2 中运行良好。我想知道 Python3 对我的期望是什么?我应该将train.py 移到我的模块之外(从技术上讲,它不是模块的一部分)吗?请提出最佳做法。

【问题讨论】:

  • net.py 是指neuralnet.py 吗?您的示例不包含名为 net.py 的文件。另外,如果 train.py 不是你的包的一部分,那么是的,你应该把它移出去。

标签: python python-3.x python-2.7 import package


【解决方案1】:

在 Python 3 中,隐式 禁止相对导入,请参阅 https://www.python.org/dev/peps/pep-0328/https://docs.python.org/release/3.0.1/whatsnew/3.0.html#removed-syntax

相对导入唯一可接受的语法是 from .[module] 导入名称。所有不以 . 开头的导入表格。被解释为 绝对进口。 (PEP 0328)

from .stuff import Stuff 是一个显式 相对导入,您“应该”尽可能使用它,并且必须尽可能在 Python 3 中使用。前往https://stackoverflow.com/a/12173406/145400 以更深入地分析相对导入。

【讨论】:

  • 不,这不起作用! from .layer.inlayers import InputLayer 抛出 SystemError: Parent module '' not loaded, cannot perform relative import
  • 您确实应该先清理您的问题(它仍然指的是 net.py)。然后,确保您正确使用了__init__.py。在那里,您指定包的公共接口。也就是说,在neuralnet/__init__.py 中,您最好导入所有相关的内容,并通过__all__ 控制应该暴露给外部的内容。与您的图层包相同。神经网络包应该只从层中导入您在layers/__init__.py 中明确公开的那些实体。
  • 嗯,隐式绝对导入并不是完全禁止。它们只是不存在
【解决方案2】:

相对导入用法从python2改为python3,

相对导入唯一可接受的语法是from .[module] import name。所有不以 . 开头的导入表格。被解释为绝对进口。 (PEP 0328)

Python 的 -m 开关允许将模块作为脚本运行。当您运行位于包内的模块时,相对导入无法正常工作。 Python 2.6 的修复 为模块添加了__package__ 属性。当此属性存在时,相对导入将与此属性的值相关,而不是与 __name__ 属性相关。 (PEP 0366)

您的问题:

  1. 您会收到SystemError: Parent module '' not loaded, cannot perform relative import 或 在 Python3.5 及以后的版本中,您会得到 ImportError: attempted relative import with no known parent package 您运行python neuralnet.py 并尝试导入from . import layers,因为您的__package__ 将是None,而PYTHONPATH 将只有当前文件(而不是其父文件),因此它找不到layer

您可以像这样运行模块:

python -m neuralnet.neuralnet

您的__package__ 将是neuralnet,因此您将能够导入其中的neuralnet 模块。

或者你可以这样做:

neuralnet 包中的__init__.py 更新为:

import os
import sys
sys.path.append(os.path.dirname(os.path.realpath(__file__)))

然后运行你的脚本neuralnet.py,上面的行会将neuralnet目录添加到PYTHONPATH。

  1. layer 不是您的 PYTHONPATH 中的模块时,您会得到 ImportError: No module named 'layer',因此 安装它将其添加到 PATH 使用

    import sys
    sys.path.append("/path/to/layer")
    

背景:

Guido(Python作者)的部分信息:

... 在 2.4 中,我们为相对导入引入了前导点符号, 同时仍然允许在没有前导点的情况下进行相对导入。在 2.5 我们可以开始警告没有前导点的相对导入 (尽管这无疑会引起那些拥有 仍然需要使用 2.3 的代码)。 在 3.0 中,我们可以取消模棱两可的导入。

多个点的用例应该很明显:在一个高度 结构化包,一个子包中的模块必须有一种方法 从同一个父包的另一个子包进行相对导入。

剩下的问题是语法到底是什么。一世 建议扩展 from 子句以允许在 带点的名称,如果至少有一个,则使带点的名称可选 找到前导点。我建议不要更改 from-less 导入。

例子:

  from .foo import bar
  from .foo.bar import xxx
  from . import foobar as barfoo
  from ..foo.bar import *
  from ... import foobar, barfoo

要读取的相关 PEP:PEP-328

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-06
    • 2018-06-04
    • 2018-08-05
    • 1970-01-01
    • 2016-07-19
    • 2016-10-09
    相关资源
    最近更新 更多