Python没有名为X absolute imports的模块

2024-09-29 00:22:26 发布

您现在位置:Python中文网/ 问答频道 /正文

在我开始之前,我想说-我知道,有很多类似的问题,但是我找不到我问题的答案。我有这样一个dir结构:

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

运行.sh

python3 project/C/C/foo.py

食品

from project.A.somelib import somefunc


VS代码实际上获得了foo.py中的智能感知——它告诉我可以从somelib导入什么函数/变量。但是当我运行run.sh时,我得到了一条错误消息:

^{pr2}$

有没有一种方法可以在保留目录结构的同时解决这个问题?在


  • 添加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
  • 我不能安装任何东西
  • 我没有sudo权限
  • 我不能创建一个virtualenv,因为脚本应该是可下载和快速执行的

Tags: pathrun答案pyproject脚本fooinit
3条回答

鉴于您的代码,我无法重现这一点(假设run.sh只是启动一个脚本)。在

你确定这不是循环进口吗?在

$ 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!

像VSCode或Pycharm这样的ide对一个项目有自己的假设,并且通常会正确地链接模块,即使最终运行代码的解释器不能做到

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


快速破解

您只需手动将路径添加到sys.path,方法是在任何其他导入发生之前在foo.py中运行import sys; sys.insert(0, '/home/dabljues/projects/project/project/'),或者在run.sh之前在shell中运行export PYTHONPATH="${PYTHONPATH}:/home/dabljues/projects/project/project/"。在


安装项目

既然看起来您正在开发一个库,那么您还可以使用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'),
)

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

^{pr2}$

这将在您的python3可执行文件的site-packages中放置一个指向项目根的链接,当您使用python3运行任何内容时,都可以访问该根。在


测试

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

跑步运行.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。在

改变你的运行.sh作为模块运行foo的脚本。python3 -m proj.C.C.foo

相关问题 更多 >