从不同层次结构中导入 Python 模块

时间:2023-04-17
本文介绍了从不同层次结构中导入 Python 模块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

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

Within the top level of my git repository, I have the following file structure:

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

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

Sometimes I want to import the generate module from within the tasksets module when I run the tasksets module as a script, so tasksets includes the following import:

import generate

其他时候我想从 training 模块中导入 tasksets 模块,所以 training 包含以下导入:

Other times I want to import the tasksets module from within the training module, so training contains the following import:

import tasksets

但是,这个设置给我带来了问题.当我将 tasksets 作为脚本运行时,tasksets 可以很好地导入 generate,但是如果我在其中导入 tasksets 则会引发错误training 当我将 training 作为脚本运行时(我认为是因为 training 无法在其中找到 generate 作为脚本默认路径).我尝试使用 __init__.py 文件、相对导入等查看各种其他 StackOverflow 问题和答案.目前,我的解决方法是在 tasksets:

However, this setup is giving me problems. tasksets can import generate fine when I run tasksets as a script, but throws an error if I import tasksets inside training when I run training as a script (I think because training can't find generate as a script within the default path). I've tried looking at all sorts of other StackOverflow questions and answers, using __init__.py files, relative imports, etc. Currently, my workaround is to use the following lines inside tasksets:

if __name__ == "__main__": import generate
else: from data import generate

但这感觉不对(而且我的 IDE 也不喜欢它).请有人可以解释如何使用正确的 __init__.py 文件分类和导入语句,以便我可以在运行 tasksets 时导入 generate 作为脚本,在运行 training 作为脚本时还要导入 tasksets?

But this doesn't feel right (and my IDE don't like it neither). Please can someone explain how to use the right assortment of __init__.py files and import statements such that I can import generate when running tasksets as a script, and also import tasksets when running training as a script?

推荐答案

你最好使用经典的 Python 模块/包架构.

You better use a classical Python module / package architecture.

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

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

To use your app, go into projectname/../ directory (one level upper projectname/) and run python -m projectname. This will execute projectname/__main__.py.

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

In __main__.py you will write something like:

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 将是您的应用/脚本的唯一入口点.
  1. You will use absolute import path (starting by your module name and a dot, projectname.)
  2. You will import your submodules out of the if __name__ == '__main__'
  3. __main__.py will be the only entry-point of your app/script.

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

In any other file, you will use the same syntax and paths to import other modules:

data/generate.py:

from projectname.data import tasksets

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

<小时>

我不太喜欢的东西,但我不确定是否有 PEP 否认它,

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

In your projectname/__init__.py file you can write:

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

所以你的两个子模块将被导入你的主范围__init__.py,所以你可以从这个范围导入子模块,比如

So your two submodules will be imported into your main scope __init__.py, so you are able to import the submodules from this scope, like

data/generate.py:

from projectname import generate

但同样,我并不真正喜欢这种方式(因为显式优于隐式.)

But again, I don't really enjoy this way of doing (because Explicit is better than implicit.)

最后一点,

  • 你也可以使用python projectname/__main__.py命令,不过我还是推荐python -m projectname
  • 您可以使用 setuptoolssetup.py 文件> 在您的系统上安装"您的应用程序,只需运行 projectname 命令即可运行它.
  • You can also use python projectname/__main__.py command, but I still recommend python -m projectname
  • You can create a setup.py file using setuptools to "install" your app on your system and simply run projectname command to run it.

这篇关于从不同层次结构中导入 Python 模块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

上一篇:关于 cmdclass 参数的 pip3 和 `python3 setup.py install` 之间的区别 下一篇:获取通过 pip 安装的软件包的安装日期和时间

相关文章