问题描述
在我的 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()
- 您将使用绝对导入路径(以您的模块名称和一个点开头,
projectname.
) - 您将从
if __name__ == '__main__'
中导入子模块 __main__.py
将是您的应用/脚本的唯一入口点.
- You will use absolute import path (starting by your module name and a dot,
projectname.
) - You will import your submodules out of the
if __name__ == '__main__'
__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 recommendpython -m projectname
- You can create a
setup.py
file using setuptools to "install" your app on your system and simply runprojectname
command to run it.
这篇关于从不同层次结构中导入 Python 模块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!