【问题标题】:Python package cannot find one of its modules after installationPython包安装后找不到它的模块之一
【发布时间】:2021-08-16 14:36:27
【问题描述】:

我正在尝试构建一个 Python 包。为简化起见,我将仅提及与问题相关的部分: 包(目录)名为moranpycess,里面有三个相关文件:

  1. 整个包的initfile __init__.py:
from .Individual import Individual
from .MoranProcess import MoranProcess
  1. 一个名为 Individual 的模块,其中包含一个类 Individual

  2. 一个名为MoranProcess 的模块包含一个类MoranProcess。在顶部,它使用:import Individual 导入前一个模块。

我用python -m pip install .安装包
然后我运行一个测试,看包是否可以正常导入:python -c 'import moranpycess'.

我明白了:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/home/runner/work/angry-moran-simulator/angry-moran-simulator/moranpycess/__init__.py", line 18, in <module>
    from .MoranProcess import MoranProcess
  File "/home/runner/work/angry-moran-simulator/angry-moran-simulator/moranpycess/MoranProcess.py", line 22, in <module>
    import Individual
ModuleNotFoundError: No module named 'Individual'
Error: Process completed with exit code 1.

这对我来说很奇怪,因为 Python 解释器似乎可以找到包,包导入相应的类,但解释器也尝试执行顶级模块导入并且(我不知道为什么)它确实找不到模块...
我在这里做错了吗?

编辑:

目录结构:

└── moranpycess
    ├── Individual.py
    ├── MoranProcess.py
    └── __init__.py

更新

我正在考虑这里提出的解决方案:
https://stackoverflow.com/a/49375740/2340598
但是我不知道这是否是组织包的“正确”方式......

【问题讨论】:

  • 尝试删除值前的.
  • 也许您应该使用带点import .Individualfrom . import Individual 的相对导入。或者也许你应该再次使用from .Individual import Individual
  • @furas: (1) 是 SyntaxError,(2) 和 (3) 产生另一个问题 ImportError: attempted relative import with no known parent package
  • 您应该显示文件夹和文件的结构 - 这样我们就可以重现这种情况并对其进行测试。
  • @furas:添加了显式目录tree

标签: python python-module python-packaging


【解决方案1】:

相对导入比绝对导入更难获得。它们也更脆弱(例如,如果你移动一个文件进行导入,它会中断),所以除非你有充分的理由使用相对导入,否则我建议只使用绝对导入。

然后,您在最顶层 __init__.py 中定义的公共 API 将如下所示:

from moranpycess.MoranProcess import MoranProcess

__all__ = ["MoranProcess"]  # import hint that some tools use

虽然仍然可以通过以下方式在内部(例如在MoranProcess.py)导入非公共对象:

from moranpycess.Individual import Individual 

绝对导入的好处在于,无论您在包中(或包外)的哪个位置,它们看起来总是一样的。


如果这样做,已安装您的软件包的用户应该能够像这样使用您的对象:

from moranpycess import MoranProcess  # directly gets the object, not module

您应该尽量避免与sys.path 混淆以使您的导入工作,主要是因为这不是必需的。如果您所做的只是编写旨在以常规方式使用的常规 python 代码,那么内置的导入机制应该可以很好地服务于您的用例。

如果我要导入一个包并注意到 sys.path 发生了变化,我会怀疑是恶作剧并开始寻找替代方案。

【讨论】:

  • 我不确定 initfile 中是否需要 from moranpycess.Individual import Individual ,因为它是一个仅由 MoranProcess 模块使用(和导入)的内部类,而不是由用户使用。而且我不想将它暴露给用户。在那之后,我认为它也不应该在__all__ 字段中......删除它可以吗? MoranProcess 模块还能找到它吗?如果是这样 - 它应该如何导入类Individual
  • 我明白了,好像我误解了一点。它现在适合您的问题吗?
  • 是的!这正是我想要的,谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-09
  • 1970-01-01
  • 1970-01-01
  • 2022-01-17
  • 1970-01-01
相关资源
最近更新 更多