2017-08-18 19 views
1

我的程序有一个结构,像这样:相对进口结构

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 
+0

'mod2'不在'scripts.sub2' – datta

回答

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条件加载它们,同时保持文件都在同一个目录中,SAN的__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 

这是值得指出的是,无论你导入的库或包的一部分,整个包被无论如何进口的 - 它只是没有在范围内的所有可用的。

+1

您应该包含指向文档源的链接。 –

+0

好点,完成! – nlsdfnbch

+0

当我执行其中任何一个时,我都会得到''no module named scripts''。同样,只要调用'import mod2'即可,即使它在'mod3/mod4'中。但我应该可以做你说的话;不知道为什么我不能。 – datta