相对进口结构

时间:2017-08-18 13:27:28

标签: python

我的程序有这样的结构:

scripts/
     __init__.py
     mod1.py
     mod2.py
     sub1/
         __init__.py
         mod3.py
     sub2/
         __init__.py
         mod4.py 

所有程序都以mod1.py启动,根据提供的系统参数选择要运行的后续脚本(mod3/mod4.py)。因此导入时的顶级目录为scripts/

说我运行我的程序,>mod1.py 3执行sub1.mod3。在mod3内我需要mod2中定义的函数(该模块保存mod3/mod4的重用代码块)。

当我尝试from .. import mod2时,我得到的ValueError我试图在顶级目录之外进行相对导入。我在语法上引用docs,如果我们将它与我的情况进行比较,mod3.py将是当前模块(在mod1.py之后)调用它。

我如何尝试进行相对进口有什么问题?

mod1.py

import sys

def imp(module):
    m = __import__(module) # equivalent to import module as m
    m.start()

if __name__ == '__main__':
    mods = {'3': 'sub1.mod3',
            '4': 'sub2.mod4'}

    imp(mods[sys.argv[1]])

mod3.py

from .. import mod2  # fails
import mod2  # works; guessing since import considers mod1 location top-level
.
.
.
def start():
    # do stuff

1 个答案:

答案 0 :(得分:2)

你说:

  

所有程序都以mod1.py启动,它根据提供的系统参数选择运行哪个后续脚本(mod3 / mod4.py)。因此导入时的顶级目录是scripts /。

From the docs(6.4.2包内引用):

  

请注意,相对导入基于当前模块的名称。由于主模块的名称始终为“__main__”,因此用作Python应用程序主模块的模块必须始终使用绝对导入。

因此您必须在文件中使用绝对导入。

所以你的代码应该是

from scripts.mod2 import X

from scripts import mod2

此外,我不确定你为什么要这样做。 将两个模块保存在单独的包中并使用if条件加载它们会更简单,同时将文件保存在同一目录中,没有__init__.py

if sys.argv[1] == '3':
    import mod3
elif sys.argv[2] == '4':
    import mod4

如果必须将它们保存在单独的文件夹中,请使用此结构:

scripts/
    mod1.py
    pkg/
        __init__.py
        mod2.py
        sub1/
            __init__.py
            mod3.py
        sub2/
            __init__.py
            mod4.py

使用此结构,您的相对导入应该有效。然后导入:

if sys.argv[1] == '3':
    from pkg.sub1 import mod3
elif sys.argv[2] == '4':
    from pkg.sub2 import mod4

值得注意的是,无论您导入的库或软件包的哪个部分,整个软件包都会被导入 - 它只是在范围内不可用。