繁体   English   中英

Python - ModuleNotFoundError:没有模块命名

[英]Python - ModuleNotFoundError: No module named

我是 Python 的新手,我在这个简单的示例中遇到以下错误:

这是我的项目结构:

python_project
.
├── lib
│   ├── __init__.py
│   └── my_custom_lib.py
└── src
    ├── __init__.py
    └── main.py

这是我执行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

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

这是我的main.py

from lib import my_custom_lib

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

do_something('Hello World!')

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

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

  • 如果它属于您的代码,只需将lib/移动到src/中。 如果是外部 package,则应按照 Henrique Branco 所述安装 pip。
  • src/之外有一个顶级脚本,用于导入和运行src.main 这会将顶级目录添加到 python 路径。
  • src/main.py修改sys.path以包含顶级目录。 这通常是不受欢迎的。
  • 使用python -m src.mainsrc/main.py作为模块调用,这会将顶级目录添加到 python 路径。 输入有点烦人,而且您需要更改所有导入。

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

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

# 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',
    ],
  },
)

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

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

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

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

您错误地使用了from a import b 它应该是这样的:

import lib.my_custom_lib

另一种方法用于从模块中导入某些方法、函数和类,而不是模块本身。 要从 my_custom_lib 模块导入特定的 function,它看起来像这样:

from lib.my_custom_lib import foo

尝试使用相对导入:

from..lib import my_custom_lib

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

.
|__ main.py
|__ lib
|   |__ __init__.py
|   |__ your_custom_lib.py
|__ another_python_package
    |__ __init__.py
    |__ another_python_scripts

之后,您的项目目录中的python main.py将起作用。

在我的情况下,第 1 行的可视代码实际错误

我没有导入 _typeshed 模块,但默认情况下它是他们的,所以如果您在第 1 行中找到,请删除该模块

MarkM 的回答还是很出色的; 我现在正在使用 PyPi。 我试图消除他所说的“当前目录”的歧义。 如果我的困惑是一个预期的功能,我就是这样做的。

vagrant@testrunner:~/pypath$ tree
.
├── proga
│   └── script1.py
└── progb
    └── script1.py

script1.py 在两个目录中是相同的:

#!/usr/bin/env python3
import sys
print(sys.path)

哪里运行它没有区别, PYTHONPATH在包含我指定的脚本的目录之前添加:

vagrant@testrunner:~/pypath/proga$ ./script1.py 
['/home/vagrant/pypath/proga', '/usr/lib/python38.zip', '/usr/lib/python3.8', '/usr/lib/python3.8/lib-dynload', '/home/vagrant/.local/lib/python3.8/site-packages', '/usr/local/lib/python3.8/dist-packages', '/usr/lib/python3/dist-packages']
vagrant@testrunner:~/pypath/proga$ ../progb/script1.py 
['/home/vagrant/pypath/progb', '/usr/lib/python38.zip', '/usr/lib/python3.8', '/usr/lib/python3.8/lib-dynload', '/home/vagrant/.local/lib/python3.8/site-packages', '/usr/local/lib/python3.8/dist-packages', '/usr/lib/python3/dist-packages']

对我来说,在这种情况下使用显式路径导入效果最好。 如果您需要 go 在树中使用“..”。 管道有点麻烦,但它总是有效的。

path = os.path.abspath(os.path.join(pathlib.Path(__file__).parent.absolute(), '..', 'subdir', 'myFile.py'))
loader = importlib.machinery.SourceFileLoader('myFile', path)
spec = importlib.util.spec_from_loader('myFile', loader)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)

# now use the module:
module.myMethod()
myClassInstance = module.myClass()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM