Python 没有名为 X 的模块 - 绝对导入

Python no module named X - absolute imports

在开始之前我想说 - 我知道有无数类似的问题,但我找不到问题的答案。我有这样的目录结构:

.
├── project
│   ├── A
│   │   ├── __init__.py
│   │   └── somelib.py
│   ├── B
│   ├── C
│   │   └── C
│   │       ├── foo.py
│   │       └── __init__.py
│   └── __init__.py
└── run.sh

run.sh:

python3 project/C/C/foo.py

foo.py:

from project.A.somelib import somefunc


VS Code 实际上在 foo.py 中获得了智能感知 - 它告诉我可以从 somelib 导入什么 funcitons/variables。但是当我 运行 run.sh 时,我收到此错误消息:

from project.A.somelib import somefunc
ModuleNotFoundError: No module named 'project'

有没有办法在保留这个目录结构的同时解决这个问题?


['/home/dabljues/projects/project/project/C/C', '/usr/lib/python37.zip', '/usr/lib/python3.7', '/usr/lib/python3.7/lib-dynload', '/usr/lib/python3.7/site-packages']

限制:

根据您的代码,我无法重现此内容(假设 run.sh 刚刚启动一个脚本)。

你确定这不是 e.g. 的情况吗?循环导入?

$ mkdir -p project/A project/C/C
$ cat > project/C/C/foo.py
print('moof!')
$ cat > project/A/somelib.py
print('beef!')
$ cat > script.py
import project.A.somelib
import project.C.C.foo
$ tree
.
├── project
│   ├── A
│   │   └── somelib.py
│   └── C
│       └── C
│           └── foo.py
└── script.py
$ python3 script.py
beef!
moof!

将您的 run.sh 脚本更改为 运行 foo 作为模块。 python3 -m proj.C.C.foo

运行 python 打包模式有帮助。

1) 为每个路径添加 __init__.py

.
├── project
│   ├── A
│   │   ├── __init__.py
│   │   └── somelib.py
│   ├── B
│   ├── C
│   │   ├── __init__.py
│   │   └── C
│   │       ├── foo.py
│   │       └── __init__.py
│   └── __init__.py
└── run.sh

2) 在foo.py中使用相对路径导入模块:

from ...A.somelib import somefunc

3) 运行 python 打包模式:

python -m project.C.C.foo

对我有用。

像 VSCode 或 Pycharm 这样的 IDE 对项目做出了自己的假设,并且通常会正确 link 模块,即使最终 运行 代码的解释器也是如此不能。

无法找到 project.A.somelib 的原因在您的 sys.path 输出中可见,它为您提供了 python 将搜索模块的位置。由于 '/home/dabljues/projects/project/project' 不包含在内,因此 python 无法在 运行 时间内解决它。


快速破解

您可以手动将路径添加到 sys.path,或者在源文件中通过 运行ning import sys; sys.insert(0, '/home/dabljues/projects/project/project/')foo.py 之前在任何其他导入发生之前,或者通过运行宁export PYTHONPATH="${PYTHONPATH}:/home/dabljues/projects/project/project/"在你的shell之前run.sh.


正在安装项目

既然您正在开发一个库,您不妨使用 python 提供的机制来使库可共享,从而解决任何导入问题。将最小的 setup.py 添加到项目根目录(即 /home/dabljues/projects/project/project/setup.py):

from setuptools import setup, find_packages


setup(
    name='project',
    version='0.1.0',
    packages=find_packages('project'),
)

并以可编辑模式安装您的项目:

$ python3 -m pip install -e .

这将在您的 python3 可执行文件的 site-packages 中放置一个 link 指向项目根目录,这样您就可以在 运行 使用 [=24] 的任何内容时访问它=].


测试

我在所有 python 文件的顶部包含了 print(__name__) 以获得一些输出。

运行ning run.sh 没有安装包:

$ sh run.sh 
Traceback (most recent call last):
  File "project/C/C/foo.py", line 1, in <module>
    from project.A.somelib import somefunc
ModuleNotFoundError: No module named 'project'

安装后

$ sh run.sh 
__main__
project.A.somelib

如您所见,project.C.C.foo 作为脚本执行,但它会找到所有以 project 开头的导入,因为安装了 project