相对imp中的超出顶层的包错误

2024-04-26 10:02:01 发布

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

关于python 3中的相对导入,这里似乎已经有很多问题了,但是经过这些问题的研究,我仍然没有找到我的问题的答案。 所以这就是问题所在。

我有一个包裹如下

package/
   __init__.py
   A/
      __init__.py
      foo.py
   test_A/
      __init__.py
      test.py

在test.py中有一行:

from ..A import foo

现在,我在package的文件夹中,运行

python -m test_A.test

我收到消息了

"ValueError: attempted relative import beyond top-level package"

但如果我在package的父文件夹中,例如,我运行:

cd ..
python -m package.test_A.test

一切都很好。

现在我的问题是: 当我在package的文件夹中,并且我以test_A.test的形式运行测试A子包中的模块时,根据我的理解,..A只上升一个级别,它仍然在package文件夹中,为什么它会给出消息说beyond top-level package。导致此错误消息的确切原因是什么?


Tags: 答案frompytestimport文件夹消息package
3条回答
import sys
sys.path.append("..") # Adds higher directory to python modules path.

试试这个。 为我工作。

编辑:这个问题在其他问题上有更好/更连贯的答案:


为什么不起作用?这是因为python不记录从何处加载包。所以当你做python -m test_A.test的时候,它基本上只是抛弃了test_A.test实际上存储在package中的知识(即package不被视为包)。尝试from ..A import foo是试图访问它不再具有的信息(即加载位置的同级目录)。这在概念上类似于在math中的文件中允许from ..os import path。这会很糟糕,因为您希望包是不同的。如果他们需要使用另一个包中的某些内容,那么他们应该使用from os import path全局引用它们,并让python计算出$PATH$PYTHONPATH的位置。

当您使用python -m package.test_A.test时,使用from ..A import foo解析很好,因为它跟踪package中的内容,并且您只访问加载位置的子目录。

为什么python不将当前工作目录视为一个包?没有线索,但天哪,这很有用。

假设:
如果您在package目录中,Atest_A是单独的包。

结论:
..A只允许在包内导入。

进一步说明:
如果希望强制将包放置在sys.path上的任何路径上,则使相对导入仅在包中可用是很有用的。

编辑:

Am I the only one who thinks that this is insane!? Why in the world is the current working directory not considered to be a package? – Multihunter

当前工作目录通常位于sys.path中。所以,那里的所有文件都是可导入的。这是自Python 2以来的行为,当时还不存在包。将运行目录设置为包将允许将模块导入为“import.a”和“import a”,这将是两个不同的模块。也许这是一个不一致的考虑。

相关问题 更多 >