想象一下这个目录结构:

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)


当前回答

我把这个写在这里供我自己参考。我知道这不是好的Python代码,但我需要一个我正在进行的项目的脚本,我想把脚本放在脚本目录中。

import os.path
import sys
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))

其他回答

一种简单的方法是在运行时将当前目录追加到PATH,如下所示:

import pathlib   
import sys
sys.path.append(pathlib.Path(__file__).parent.resolve())
import file_to_import  # the actual intended import

与此问题的另一个解决方案相比,这个解决方案使用pathlib而不是os.path。

看看http://docs.python.org/whatsnew/2.5.html#pep-328-absolute-and-relative-imports。你可以这样做

from .mod1 import stuff

每个人似乎都想告诉你应该做什么,而不仅仅是回答问题。

问题是,通过将mod1.py作为参数传递给解释器,您正在以'__main__'的身份运行模块。

PEP 328:

相对导入使用模块的__name__属性来确定该模块在包层次结构中的位置。如果模块的名称不包含任何包信息(例如,它被设置为'__main__'),则相对导入将被解析,就像该模块是顶级模块一样,而不管该模块实际位于文件系统的哪个位置。

在Python 2.6中,他们添加了相对于主模块引用模块的功能。PEP 366描述了这个变化。

更新:根据Nick Coghlan的说法,推荐的替代方案是使用-m开关在包中运行模块。

我把这个写在这里供我自己参考。我知道这不是好的Python代码,但我需要一个我正在进行的项目的脚本,我想把脚本放在脚本目录中。

import os.path
import sys
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))

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

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