想象一下这个目录结构:

app/
   __init__.py
   sub1/
      __init__.py
      mod1.py
   sub2/
      __init__.py
      mod2.py

我正在编写mod1,我需要从mod2中导入一些东西。我该怎么做呢?

我试过…sub2导入mod2,但我得到了一个“尝试相对导入非包”。

我搜索了一下,但只找到了“sys”。路径操纵“黑客”。没有干净的方法吗?


编辑:我所有的__init__.py目前是空的

Edit2:我试图这样做是因为sub2包含跨子包共享的类(sub1、subX等)。

Edit3:我正在寻找的行为与PEP 366中描述的相同(感谢John B)


当前回答

下面是一个适合我的解决方案:

我做相对进口从..Sub2导入mod2 然后,如果我想运行mod1.py,然后我进入app的父目录,使用python -m开关运行模块,如python -m app.sub1.mod1。

相对导入出现此问题的真正原因是相对导入通过接受模块的__name__属性来工作。如果模块是直接运行的,那么__name__将被设置为__main__,并且它不包含任何关于包结构的信息。而且,这就是python抱怨在非包错误中相对导入的原因。

因此,通过使用-m开关,您可以向python提供包结构信息,通过这些信息,python可以成功地解析相对导入。

在进行相对导入时,我多次遇到过这个问题。而且,在阅读了之前所有的答案后,我仍然无法弄清楚如何以一种干净的方式解决它,而不需要在所有文件中放入样板代码。(尽管有些评论真的很有帮助,感谢@ncoghlan和@XiongChiamiov)

希望这能帮助那些与相对进口问题作斗争的人,因为通过PEP真的不好玩。

其他回答

在John B所说的之上,设置__package__变量似乎会有所帮助,而不是改变__main__,这可能会搞砸其他事情。但就我所测试的而言,它并没有完全发挥应有的作用。

我有同样的问题,PEP 328或366都没有完全解决这个问题,因为两者在一天结束时,都需要包的头包含在sys. exe中。据我所知,这是一条道路。

我还应该提到,我没有找到如何格式化字符串应该进入这些变量。是package_head.subfolder吗?Module_name”或者什么?

main.py
setup.py
app/ ->
    __init__.py
    package_a/ ->
       __init__.py
       module_a.py
    package_b/ ->
       __init__.py
       module_b.py

运行python main.py。 Main.py执行如下操作:导入app.package_a.module_a Module_a.py会导入app.package_b.module_b

或者2或3可以使用:from app.package_a import module_a

只要你的PYTHONPATH中有app,这就可以工作。Main.py可以在任何地方。

所以你写了一个setup.py来复制(安装)整个应用程序包和子包到目标系统的python文件夹,main.py到目标系统的脚本文件夹。

这个方法查询并自动填充路径:

import os
import inspect
currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
parentdir = os.path.dirname(currentdir)
os.sys.path.insert(1, parentdir)
# print("currentdir = ", currentdir)
# print("parentdir=", parentdir)

你必须将模块的路径附加到PYTHONPATH:

export PYTHONPATH="${PYTHONPATH}:/path/to/your/module/"

下面是一个适合我的解决方案:

我做相对进口从..Sub2导入mod2 然后,如果我想运行mod1.py,然后我进入app的父目录,使用python -m开关运行模块,如python -m app.sub1.mod1。

相对导入出现此问题的真正原因是相对导入通过接受模块的__name__属性来工作。如果模块是直接运行的,那么__name__将被设置为__main__,并且它不包含任何关于包结构的信息。而且,这就是python抱怨在非包错误中相对导入的原因。

因此,通过使用-m开关,您可以向python提供包结构信息,通过这些信息,python可以成功地解析相对导入。

在进行相对导入时,我多次遇到过这个问题。而且,在阅读了之前所有的答案后,我仍然无法弄清楚如何以一种干净的方式解决它,而不需要在所有文件中放入样板代码。(尽管有些评论真的很有帮助,感谢@ncoghlan和@XiongChiamiov)

希望这能帮助那些与相对进口问题作斗争的人,因为通过PEP真的不好玩。