Python3正确导入相对或绝对的方式?

时间:2015-02-08 23:38:11

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

我正在编写一个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
    layers/
        __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.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

2)运行classify.py(在模块外部)。

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

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

由于 勒凯什

2 个答案:

答案 0 :(得分:3)

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

  

相对导入的唯一可接受的语法来自。[模块]   导入名称。所有导入表单都不以。被解释为   绝对进口。 (PEP 0328)

from .stuff import Stuff显式相对导入,您应该"应该"尽可能使用,并且只要有可能,必须在Python 3中使用。前往https://stackoverflow.com/a/12173406/145400进行更深入的相关进口分析。

答案 1 :(得分:0)

相对导入用法已从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模块。

或者您可以执行以下解决方法:

__init__.py软件包中的neuralnet更新为:

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

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

  1. 如果ImportError: No module named 'layer'不是PYTHONPATH中的模块,则会得到layer,因此安装将其添加到PATH strong>使用

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

背景:

来自Guido(Python的作者)的部分消息:

...在2.4版中,我们引入了相对导入的前导点符号, 同时仍允许相对导入而没有前导点。在 2.5我们可以开始警告有关相对导入而没有前导点 (尽管这无疑会引起那些 需要与2.3一起使用的代码)。 在3.0中,我们可以取消模糊的导入。

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

剩下的问题仍然是确切的语法。一世 建议扩展from子句,以允许一个或多个点 点名,如果至少一个,则使点名可选 找到前导点。我建议不要更改最少导入。

示例:

  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