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'
有没有办法在保留这个目录结构的同时解决这个问题?
- 添加
project/__init__.py
没有任何改变
foo.py
中的 sys.path
看起来像这样:
['/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']
限制:
- 在 运行 脚本
之前,我无法修改文件中的 sys.path
和 PYTHONPATH
- 我无法通过 pip 安装任何东西
- 我没有 sudo-access
- 我无法创建 virtualenv,因为脚本应该可以下载并快速执行
根据您的代码,我无法重现此内容(假设 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
。
在开始之前我想说 - 我知道有无数类似的问题,但我找不到问题的答案。我有这样的目录结构:
.
├── 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'
有没有办法在保留这个目录结构的同时解决这个问题?
- 添加
project/__init__.py
没有任何改变 foo.py
中的sys.path
看起来像这样:
['/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']
限制:
- 在 运行 脚本 之前,我无法修改文件中的
- 我无法通过 pip 安装任何东西
- 我没有 sudo-access
- 我无法创建 virtualenv,因为脚本应该可以下载并快速执行
sys.path
和 PYTHONPATH
根据您的代码,我无法重现此内容(假设 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
。