Python - ModuleNotFoundError:没有命名模块

Nic*_*las 9 python python-module init importerror

我是 Python 新手,在这个简单示例中出现以下错误:

这是我的项目结构:

python_project
.
??? lib
?   ??? __init__.py
?   ??? my_custom_lib.py
??? src
    ??? __init__.py
    ??? main.py
Run Code Online (Sandbox Code Playgroud)

这是我执行src/main.py文件时的错误:

?  python_project  python src/main.py

Traceback (most recent call last):
  File "src/main.py", line 3, in <module>
    from lib import my_custom_lib
ImportError: No module named lib
Run Code Online (Sandbox Code Playgroud)

如果我将main.py文件移动到根目录,然后再次执行此文件,则可以工作...但无法在src/目录中工作

这是我的main.py

from lib import my_custom_lib

def do_something(message):
        my_custom_lib.show(message)

do_something('Hello World!')
Run Code Online (Sandbox Code Playgroud)

注意:当我从Pycharm执行相同的代码时工作正常,但不能从我的终端执行。

Mar*_*rkM 7

您的PYTHONPATH设置为您执行的程序的当前目录。因此,如果您在目录内执行某些操作src,它将永远无法找到该目录,lib因为它在路径之外。有几个选择;

  • 如果它属于您的代码,只需lib/进入src/。如果它是一个外部包,它应该像 Henrique Branco 提到的那样安装 pip。
  • src/导入和运行之外有一个顶级脚本src.main。这会将顶级目录添加到 python 路径。
  • src/main.py修改sys.path中包含顶级目录。这通常是不受欢迎的。
  • src/main.py作为模块调用python -m src.main,它将顶级目录添加到 python 路径。打字很烦人,而且您需要更改所有导入。

  • 无需重组您的项目,在源代码之外进行测试是很好的做法!如果“src”和“tests”都有“__init__.py”,并且假设您正在编写传统的“unittest.TestCase”测试,则可以利用标准的unittest模块来[发现](https://docs.python .org/3/library/unittest.html#test-discovery)并使用顶级目录中的简单“python -m unittest”运行测试。 (2认同)

小智 6

您的 main.py 脚本应该位于目录结构中所有 Python 包之上。尝试将您的项目更新为以下结构:

.
|__ main.py
|__ lib
|   |__ __init__.py
|   |__ your_custom_lib.py
|__ another_python_package
    |__ __init__.py
    |__ another_python_scripts
Run Code Online (Sandbox Code Playgroud)

之后,python main.py在你的项目目录中就可以工作了。


Pes*_*o_T 5

如果我可以添加到MarkM 的答案中,如果您想保留当前的目录结构并仍然使其工作,您可以setup.py在根目录中添加一个,您可以在其中使用setuptools创建一个可以安装的包。

如果您的文件包含以下内容:

# setup.py

from setuptools import find_packages, setup

setup(
  name='foo',
  version=`1.0.0`,
  packages=find_packages(),
  entrypoints={
    'console_scripts': [
      'foo=src.main:main',
    ],
  },
)
Run Code Online (Sandbox Code Playgroud)

然后你pip install [--user] -e path/to/directory会得到一个“可编辑的包”,它实际上是你开发目录中包的符号链接,所以你所做的任何更改都不需要重新安装(除非你重新调整包结构或添加/删除/编辑入口点)。

这确实假设您src/main.py有一个主要功能。

您还需要__init__.py“包”目录中的文件,即使在 Python3 中,否则 Python 假定这些是命名空间包(不会详细介绍)并且find_packages()调用将找不到它们。

这也将允许您的相关导入工作。绝对导入仅在从入口点调用脚本时有效,而在开发目录中直接调用脚本时无效。


Hol*_*den 3

您使用的方法from a import b不正确。它应该看起来像这样:

import lib.my_custom_lib
Run Code Online (Sandbox Code Playgroud)

另一种方法用于从模块导入某些方法、函数和类,而不是模块本身。要从my_custom_lib模块导入特定函数,它将如下所示:

from lib.my_custom_lib import foo
Run Code Online (Sandbox Code Playgroud)