尝试从导入的包中导入模块时出现“ModuleNotFoundError”

新手上路,请多包涵

这是我的目录结构:

 man/
  Mans/
          man1.py
  MansTest/
          SoftLib/
                  Soft/
                      SoftWork/
                              manModules.py
          Unittests/
                    man1test.py

man1.py 包含以下 导入 语句, 我不想更改

 from Soft.SoftWork.manModules import *

man1test.py 包含以下 导入 语句:

 from ...MansTest.SoftLib import Soft
from ...Mans import man1

我需要在 man1test.py 中进行第二次 _导入_,因为 man1test.py 需要访问 man1.py 中的函数。

我在第一次导入( Soft )背后的理由是促进 man1.py 中的上述 导入 语句。

然而,与我的预期相反, man1.py 中的 导入 语句会导致:

 ModuleNotFoundError: No module named 'Soft'

当我跑步时

python3 -m man.MansTest.Unittests.man1test

从上面的目录 man/

有没有什么办法可以解决这个错误而不改变 man1.py 中的 导入 语句 并且 不向 sys.path 添加任何东西?

编辑: python3 -m man.ManTest.Unittests.man1test 从问题的原始版本改为 python3 -m man.MansTest.Unittests.man1test

原文由 strangeloop 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 616
2 个回答

首先,如果您希望能够从 man1test.py 访问 man1.py 和从 man1.py 访问 manModules.py 您需要将文件正确设置为 包和模块

包是一种通过使用“带点的模块名称”来构建 Python 模块名称空间的方式。例如,模块名称 A.B 指定一个名为 B 的子模块在一个名为 A 的包中。

导入包时,Python 会在 sys.path 上的目录中搜索包子目录。

需要 __init__.py 文件以使 Python 将目录视为包含包;这样做是为了防止具有通用名称的目录(例如 string )无意中隐藏模块搜索路径中稍后出现的有效模块。

您需要将其设置为以下内容:

 man
|- __init__.py
|- Mans
   |- __init__.py
   |- man1.py
|- MansTest
   |- __init.__.py
   |- SoftLib
      |- Soft
         |- __init__.py
         |- SoftWork
            |- __init__.py
            |- manModules.py
      |- Unittests
         |- __init__.py
         |- man1test.py

_其次_,对于由 from ...Mans import man1man1test.py 中引起的“ ModuleNotFoundError: No module named 'Soft' ”错误,记录在案的解决方案是将 man1.py 添加到 sys.path —在 MansTest 包之外。请参阅 Python 文档中 的模块搜索路径。但是如果不想直接修改 sys.path ,也可以修改 PYTHONPATH

sys.path 从这些位置初始化:

  • 包含输入脚本的目录(或未指定文件时的当前目录)。
  • PYTHONPATH (目录名称列表,与shell变量的语法相同 PATH )。
  • 安装相关的默认值。

第三,对于 from ...MansTest.SoftLib import Soft 你说“ _是为了促进 man1.py 中的上述导入语句_”,这就是导入的工作方式。如果要在 man1.py 中导入 Soft.SoftLib ,则必须设置 man1.py 以找到 Soft.SoftLib 并直接将其导入那里。

话虽如此,这就是我如何让它工作的。

人1.py:

 from Soft.SoftWork.manModules import *
# no change to import statement but need to add Soft to PYTHONPATH

def foo():
    print("called foo in man1.py")
    print("foo call module1 from manModules: " + module1())

man1test.py

 # no need for "from ...MansTest.SoftLib import Soft" to facilitate importing..
from ...Mans import man1

man1.foo()

人模块.py

 def module1():
    return "module1 in manModules"

终端输出:

 $ python3 -m man.MansTest.Unittests.man1test
Traceback (most recent call last):
  ...
    from ...Mans import man1
  File "/temp/man/Mans/man1.py", line 2, in <module>
    from Soft.SoftWork.manModules import *
ModuleNotFoundError: No module named 'Soft'

$ PYTHONPATH=$PYTHONPATH:/temp/man/MansTest/SoftLib
$ export PYTHONPATH
$ echo $PYTHONPATH
:/temp/man/MansTest/SoftLib
$ python3 -m man.MansTest.Unittests.man1test
called foo in man1.py
foo called module1 from manModules: module1 in manModules


作为一个建议,也许重新考虑那些 SoftLib 文件的目的。它是 man1.pyman1test.py 之间的某种“桥梁”吗?您现在的文件设置方式,我认为它不会像您期望的那样工作。此外,被测代码( man1.py )从测试文件夹( MansTest )下导入东西有点令人困惑。

原文由 Gino Mempin 发布,翻译遵循 CC BY-SA 4.0 许可协议

我有一个类似的问题,虽然不一样。

我的文件夹和文件具有以下结构(GUI_ML 是主文件夹):

 GUI_ML
\ Views \ login.py
\ Views \ __ init __.py
\ Controllers \ Control_login.py
\ Controllers \ __ init __.py

我需要从 login.py 导入 Control_login.py。以下代码解决了我的问题:

 import sys
import os
myDir = os.getcwd()
sys.path.append(myDir)

from pathlib import Path
path = Path(myDir)
a=str(path.parent.absolute())

sys.path.append(a)

from Controllers.Control_login import Control_login

原文由 Luis Timaná 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题