Python3 importlib.util.spec_from_file_location 带有相对路径?

问题描述 投票:0回答:1

有很多关于如何导入相对包或通过显式位置的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()

??

python
1个回答
0
投票
首先介绍一下背景:

    几十年来,打包一直是 Python 的祸根。
  • 尝试使用流行的和/或好的打包工具来帮助您解决此类问题。
据我所知,2024 年最受欢迎的是

诗歌。我个人最喜欢的是PDM。两者都很好,但 PDM 试图突破界限,将 Python 打包带入 21 世纪。

使用 Poetry,

poetry new <package-name>

创建正确的包结构。使用 PDM,pdm init
做类似的事情。两者都会创建一个看起来像这样的文件夹结构:

mypackage ├── pyproject.toml ├── README.md ├── mypackage │ └── __init__.py └── tests └── __init__.py
我强烈建议使用这样的工具,因为它可以帮助您解决 Python 打包的一些奇怪问题,特别是以下内容:

    您想要在包中发现的任何模块(Python 文件)都应该在其同一文件夹中具有
  • __init__.py
     文件。
    
      这种情况正在发生变化,因此不再需要该文件,但为了最佳实践,该文件将在可预见的未来存在。
  • 应该有一个同名的父文件夹和子文件夹,即包的名称。上面,我使用了包名称
  • mypackage
      这是因为顶层是用于“构建、测试和维护”包本身的文件。较低级别是包源文件本身。
    • 我实际上添加了另一层,因此构建、测试和维护文件位于 mypackage
    • ,源文件位于
    • mypackage/src/mypackage
      。这是因为其他 CI/CD 工具会查找 
      src
       目录。选择您的偏好。
      
      
    回答你的问题:
记住上述内容,

正确的导入方式

就是简单的import <module or package>。这是正确的,因为:

(对于人类而言)最容易阅读。

    这是最灵活的。
  • 这意味着它最有可能在除您的机器之外的其他机器上运行
    • 它最好与 IDE 集成。
  • 例如,IDE 可以找到与包或模块关联的所有文档。
  • 所以如果你有

proj-dir ├── mod1 │   ├── __init__.py │ └── class1.py └── mod2    ├── __init__.py └── class2.py

然后您将
首先在顶层添加一个
__init__.py

文件,然后只需通过以下方式导入它们:

proj-dir/mod1/class1.py

文件:

import proj_dir.mod2.class2

这里有一些隐藏的花絮需要解开:

为什么斜杠[

/
    ]变成了点[
  1. .
    ]?
    
    这就是 Python(以及我所知道的所有语言)遍历包目录结构的方式。
    • 为什么
    proj-dir
  2. 变成了
  3. proj_dir
    这是 
    Python 所做的事情
      。我不记得细节了,但是 Python 不能在变量名中使用破折号,所以任何带有破折号的东西都会被破坏成下划线。这就是为什么我不喜欢使用它们......它让新用户遭受不必要的痛苦。
    • 为什么我要一路回到项目名称本身?
  4. 这是因为包裹从
  5. proj-dir
      开始。 “包”被定义为文件夹结构层次结构中包含
    • __init__.py
       文件的所有内容。因此可以向上遍历父级,直到没有 
      __init__.py
      。这也解释了为什么我说有必要在顶层添加一个 
      __init__.py
       文件,如下所示。
      
      
    请务必添加以下
  6. __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


© www.soinside.com 2019 - 2024. All rights reserved.