Python: 导入语句中无法识别父包的名称

Python: name of parent package not recognized in import statements

我知道有很多关于这个主题的问题,但我看到的大多数答案都描述了解决问题的复杂方法,在我看来,这些问题应该很简单。这是我的目录结构:

Mapper/
    LICENSE.txt
    README.txt
    setup.py
    bin/
        # nothing here, yet
    mapper/
        __init__.py
        process.py
        where.py
        # ...
        binconvert/
            __init__.py
            tocsv.py
            todict.py
            # ...

我想在所有本地开发的模块上使用绝对路径以减少混淆并避免提到的错误 here

但是,我遇到了很多问题。当我运行process.py,其中我importtocsv.py这样,

from mapper.binconvert import tocsv

我收到错误:ModuleNotFoundError: No module named 'mapper'

我知道我可以做到 from binconvert import tocsv,但就像我说的,我正在尝试让我所有本地开发的模块导入都使用绝对路径。

当我尝试像这样导入 where.py 时,我遇到了与之前在 tocsv.py 中相同的错误:

 from mapper import where

对于这个,我相信有一些方法可以使用相对 import 的点语法,但同样,我想保持我所有的路径都是绝对的。毕竟,我相信根据 python 文档的 this 段,我应该能够做到这一点:

When packages are structured into subpackages (as with the sound package in the example), you can use absolute imports to refer to submodules of siblings packages. For example, if the module sound.filters.vocoder needs to use the echo module in the sound.effects package, it can use from sound.effects import echo.

sound/                          Top-level package
      __init__.py               Initialize the sound package
      formats/                  Subpackage for file format conversions
              __init__.py
              wavread.py
              wavwrite.py
              aiffread.py
              aiffwrite.py
              auread.py
              auwrite.py
              ...
     effects/                  Subpackage for sound effects
              __init__.py
              echo.py
              surround.py
              reverse.py
              ...
     filters/                  Subpackage for filters
              __init__.py
              equalizer.py
              vocoder.py
              karaoke.py
              ...

当您执行 process.py 时,您已经位于映射程序包中。 Python 将遍历 sys.path 中定义的所有路径以查找模块,在本例中仅由 ["standard python path", "Mapper/mapper"] 构成。

在这种情况下,python 不会在这些目录中找到名为 mapper 的模块(您已经在 mapper 模块中)。

适合您的解决方案:

  1. 使用表示法:from .binconvert import tocsv(符合PEP 328
  2. 启动前从 1 个目录上移并从 Mapper 目录启动 process.py
  3. 通过添加 Mapperpath
  4. 在启动 process.py 之前更改 PYTHONPATH 环境变量

如果包含 "mapper" 包的目录位置在 sys.path:

中,您可以从 "mapper" 包的任何位置导入(使用 "from mapper.anything import that")
# in process.py
import os, sys
THIS_DIR = os.path.dirname(os.path.abspath(__file__)) #  "mapper" dir
MAPPER_ROOT_DIR = os.path.dirname(THIS_DIR) #  points to "Mapper" dir
if MAPPER_ROOT_DIR not in sys.path:
    sys.path.insert(0, MAPPER_ROOT_DIR)

您可以在出现问题的每个模块中包含此代码段。约定是在 运行 的第一个模块中设置路径(在导入任何 "own" 包之前)。 sys.path 内容在所有 运行 个模块之间共享。