从不同层次的层次导入Python模块

时间:2018-11-05 12:10:03

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

在git存储库的顶层,我具有以下文件结构:

miscellaneous Dockerfiles, readme, etc
Code/
    training.py
    data/
        generate.py
        tasksets.py

有时候,当我将generate模块作为脚本运行时,我想从tasksets模块中导入tasksets模块,因此tasksets包括以下导入: / p>

import generate

有时我想从tasksets模块中导入training模块,因此training包含以下导入:

import tasksets

但是,此设置给我带来了问题。在运行tasksets作为脚本时,generate可以很好地导入tasksets,但是在运行{{1}时,如果在tasksets中导入training会引发错误。 }作为脚本(我想是因为training在默认路径中找不到training作为脚本)。我尝试使用generate文件,相对导入等方法查看其他所有StackOverflow问题和答案。目前,我的解决方法是在__init__.py中使用以下几行:

tasksets

但这感觉不对(我的IDE也都不喜欢)。请有人解释一下如何使用正确的if __name__ == "__main__": import generate else: from data import generate 文件分类和导入语句,以便我可以在将__init__.py作为脚本运行时导入generate,并在运行时导入tasksets作为脚本运行tasksets

1 个答案:

答案 0 :(得分:0)

您最好使用经典的Python模块/包体系结构。

projectname/
    __init__.py
    __main__.py
    data/
        __init__.py
        generate.py
        tasksets.py

要使用您的应用程序,请进入projectname/../目录(上一级projectname/)并运行python -m projectname。这将执行projectname/__main__.py


__main__.py中,您将编写如下内容:

from projectname.data import generate
from projectname.data import tasksets

if __name__ == '__main__':
    generate.foo()
    tasksets.bar()
  1. 您将使用绝对导入路径(以模块名称和点projectname.开头)
  2. 您将从if __name__ == '__main__'
  3. 中导入子模块
  4. __main__.py将是您的应用/脚本的唯一入口点。

在任何其他文件中,您将使用相同的语法和路径来导入其他模块:

data/generate.py

from projectname.data import tasksets

def foo():
    print('SPAM!')
    tasksets.bar()

我不太喜欢的东西,但我不确定有人能拒绝它,

在您的projectname/__init__.py文件中,您可以编写:

from projectname.data import generate
from projectname.data import tasksets

因此,您的两个子模块将被导入到主作用域__init__.py中,因此您可以从该作用域中导入子模块,例如

data/generate.py

from projectname import generate

但是,我还是不太喜欢这种方式(因为显式比隐式更好。


最后但并非最不重要

  • 您也可以使用python projectname/__main__.py命令,但我仍然建议使用python -m projectname
  • 您可以使用setuptools创建一个setup.py文件,以在系统上“安装”您的应用程序,只需运行projectname命令即可​​运行它。