有很多关于如何导入相对包或通过显式位置的Python问题(链接到两个流行的例子)。
此外,总是有 文档
读完这篇文章后,我仍然不太清楚规范是什么,它们与模块有何关系,以及为什么需要对其进行标记。
因此,对于不理解的人,您能否尝试解释一下如何做到这一点(以编程方式以及幕后含义)
例如
如果我有
proj-dir
--mod1
--|--__init__.py
--|--class1.py
--mod2
--|--__init__.py
--|--class2.py
如何将 mod2 导入到 mod1 中?
import sys
sys.path.insert(0, "../mod2")
这在技术上是可行的,但我担心如果我尝试腌制对象并在其他地方使用它们,可能会在将来引起问题......
建议的明确位置
import importlib.util
spec = importlib.util.spec_from_file_location("module.name", "/path/to/file.py")
foo = importlib.util.module_from_spec(spec)
spec.loader.exec_module(foo)
foo.MyClass()
所以在这种情况下我只是这样做:
import importlib.util
spec = importlib.util.spec_from_file_location("mod2.class2", "../mod2/class2.py")
foo = importlib.util.module_from_spec(spec)
spec.loader.exec_module(foo)
foo.MyClass()
??
诗歌。我个人最喜欢的是PDM。两者都很好,但 PDM 试图突破界限,将 Python 打包带入 21 世纪。
使用 Poetry,poetry new <package-name>
将创建正确的包结构。使用 PDM,
pdm init
将做类似的事情。两者都会创建一个看起来像这样的文件夹结构:
mypackage
├── pyproject.toml
├── README.md
├── mypackage
│ └── __init__.py
└── tests
└── __init__.py
我强烈建议使用这样的工具,因为它可以帮助您解决 Python 打包的一些奇怪问题,特别是以下内容:
__init__.py
文件。
mypackage
。
mypackage
mypackage/src/mypackage
。这是因为其他 CI/CD 工具会查找
src
目录。选择您的偏好。
就是简单的import <module or package>
。这是正确的,因为:
proj-dir
├── mod1
│ ├── __init__.py
│ └── class1.py
└── mod2
├── __init__.py
└── class2.py
然后您将
首先在顶层添加一个
__init__.py
文件,然后只需通过以下方式导入它们:
proj-dir/mod1/class1.py
文件:
import proj_dir.mod2.class2
这里有一些隐藏的花絮需要解开:
为什么斜杠[
/
.
]?
这就是 Python(以及我所知道的所有语言)遍历包目录结构的方式。
proj-dir
proj_dir
?
这是Python 所做的事情
proj-dir
__init__.py
文件的所有内容。因此可以向上遍历父级,直到没有
__init__.py
。这也解释了为什么我说有必要在顶层添加一个
__init__.py
文件,如下所示。
__init__.py
proj-dir
├── __init__.py
├── mod1
│ ├── __init__.py
│ └── class1.py
└── mod2
├── __init__.py
└── class2.py
总结一下:上面有很多信息。其中大部分是标准的,并且需要跨多种语言进行打包。其中一些是专门针对 Python 的。将上面的信息付诸实践,我会如下调整你的包结构......即使上面写的应该是完全可用的。projdir
├── pyproject.toml
├── README.md
├── projdir
│ ├── __init__.py
│ ├── mod1
│ │ ├── __init__.py
│ │ └── class1.py
│ └── mod2
│ ├── __init__.py
│ └── class2.py
└── tests
├── __init__.py
├── test_class1.py
└── test_class2.py