如何使用Python 3中的绝对导入导入位于其父目录中的包?

时间:2015-03-06 11:03:56

标签: python python-3.x

我有一个像这样的python包目录:

proj/
  mod_a/
    __init__.py
    x.py
    submod_x/
      __init__.py
      y.py
  mod_b/
    __init__.py
    z.py

使用x.py:

import submod_x.y

z.py:

import sys, os.path
sys.path.append(os.path.abspath('../'))

import mod_a.x

现在我跑的时候:

$ python2 z.py

我用y.py

编写完成的东西

但是当我跑步时:

$ python3 z.py

我有一个例外:

Traceback (most recent call last):
File "z.py", line 4, in <module>
  import mod_a.x
File ".../proj/mod_a/x.py", line 1, in <module>
  import submod_x.y
ImportError: No module named 'submod_x'

我想知道导入包时Python 2和Python 3之间有什么区别,如何在Python 3中使用绝对导入导入位于其父目录中的包?

2 个答案:

答案 0 :(得分:3)

感谢用户的帮助。 仔细阅读PEP后,我现在能够自己回答这个问题。

首先,我需要知道3种进口:

  1. 绝对进口。

    import sys
    

    此处,“sys”是可从sys.path($ PATH)访问的模块或包名称。 Python默认情况下将脚本所在的目录插入到sys.path中。换句话说,如果我在python3 mod_b/z.py下运行proj/,python会将proj/mod_b/插入到sys.path。

  2. 明确的相对进口。

    from ..mod_a import x
    

    导入相对于当前模块的模块(可能当前工作目录$ PWD)。 python3 doc中清楚地描述了基本原理。还有一些来自PEP-0328的例子。

    注意:显式相对导入必须始终使用from <> import <>

  3. 隐式相对进口。

    import submod_x.y
    

    在python2中,这样的import语句将隐式导致相对于当前模块的导入。即如果我在python2 mod_a/x.py下运行proj/,则当前模块为x,并且将正确导入相对于submod_x.y的模块x。声明from submod_x import y等同于from .submod_x import y作为上面提到的显式相对导入。

    然而,显而易见的是隐式相对进口可能与绝对进口混淆,如PEP-0328中所述。根据{{​​3}},python3不再支持隐式相对导入。

  4. 其次,在包中运行脚本在PEP-0404中被视为Guido的反模式......

      

    我在这方面以及主要机制的任何其他提议方面都是-1。唯一的用例似乎是运行脚本,这些脚本恰好位于模块的目录中,我一直将其视为反模式。为了让我改变主意,你必须让我相信它不是。

    您可能会想到email。如果您打算这样做,请参阅上面链接中的帖子以获取解决方案。

    以下是其他一些可能对您有帮助的帖子:

    explicit relative imports work improperly

    Changes in import statement python3

答案 1 :(得分:0)

我认为你应该在x.py中执行此操作:

import mod_a.submod_x.y

从文件位置进行绝对导入是使用绝对模块名称完成的,或者像这样:

from . import submod_x.y