[英]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.main
将src/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.