beyond top level package error in relative import
关于python 3中的相对导入,这里似乎已经有相当多的问题了,但是在经历了其中的许多问题之后,我仍然没有找到我的问题的答案。所以这是个问题。
我有一个如下所示的包裹
1 2 3 4 5 6 7 8 | package/ __init__.py A/ __init__.py foo.py test_A/ __init__.py test.py |
我在test.py中有一行:
1 | from ..A import foo |
现在,我在
1 | python -m test_A.test |
我得到了信息
1 | "ValueError: attempted relative import beyond top-level package" |
但如果我在
1 2 | cd .. python -m package.test_A.test |
一切都很好。
现在我的问题是:当我在
编辑:在其他问题中有更好/更连贯的答案:
- 兄弟包导入
- 第十亿次相对进口
为什么不起作用?这是因为python不记录包的加载位置。所以当你做
当您使用
为什么python不把当前的工作目录看作一个包?不知道,但天哪,这会有用的。
1 2 | import sys sys.path.append("..") # Adds higher directory to python modules 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",这将是两个不同的模块。也许这是一个不一致的考虑。
我觉得它比
1 2 | import sys sys.path.append("..") |
在3.6中,这些解决方案都不适用于我,文件夹结构如下:
1 2 3 4 5 6 | package1/ subpackage1/ module1.py package2/ subpackage2/ module2.py |
我的目标是从模块1导入模块2。奇怪的是,最终对我起作用的是:
1 2 | import sys sys.path.append(".") |
注意单点,而不是迄今为止提到的两个点的解决方案。
编辑:以下内容帮助我澄清了这一点:
1 2 | import os print (os.getcwd()) |
在我的例子中,工作目录(出乎意料地)是项目的根目录。
如果在已经提供了好的答案之后,仍有人在挣扎,请考虑查看以下内容:
https://www.daveoncode.com/2017/03/07/how-to-solve-python-modulenotfound-no-module-named-import-error/
以上网站的基本报价:
"The same can be specified programmatically in this way:
import sys
sys.path.append('..')
Of course the code above must be written before the other import
statement.
很明显,事情必须是这样的,事后再考虑。我试图在测试中使用sys.path.append("…"),但遇到了op发布的问题。通过在其他导入之前添加import和sys.path定义,我能够解决该问题。
正如最流行的答案所表明的,基本上是因为你的
您可以通过先将相对导入更改为绝对导入,然后从以下任一项开始来解决此问题:
1 | PYTHONPATH=/path/to/package python -m test_A.test |
或者在以这种方式调用时强制使用python路径,因为:
用
这意味着在
1 2 3 4 5 6 7 8 9 10 | from os import path … def main(): … if __name__ == '__main__': import sys sys.path.append(path.join(path.dirname(__file__), '..')) from A import foo exit(main()) |
如果在上面的文件夹中有一个
1 | import alias |