想象一下这个目录结构:

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)


当前回答

用例子解释nosklo的答案

注意:所有__init__.py文件都是空的。

main.py
app/ ->
    __init__.py
    package_a/ ->
       __init__.py
       fun_a.py
    package_b/ ->
       __init__.py
       fun_b.py

app - package_a fun_a . py

def print_a():
    print 'This is a function in dir package_a'

app - package_b fun_b . py

from app.package_a.fun_a import print_a
def print_b():
    print 'This is a function in dir package_b'
    print 'going to call a function in dir package_a'
    print '-'*30
    print_a()

main.py

from app.package_b import fun_b
fun_b.print_b()

如果你运行$ python main.py,它会返回:

This is a function in dir package_b
going to call a function in dir package_a
------------------------------
This is a function in dir package_a

Main.py执行如下操作 Fun_b.py从app.package_a。Fun_a import print_a

package_b文件夹中的文件使用package_a文件夹中的文件,这就是你想要的。对吧? ?

其他回答

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

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

PEP 328:

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

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

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

用例子解释nosklo的答案

注意:所有__init__.py文件都是空的。

main.py
app/ ->
    __init__.py
    package_a/ ->
       __init__.py
       fun_a.py
    package_b/ ->
       __init__.py
       fun_b.py

app - package_a fun_a . py

def print_a():
    print 'This is a function in dir package_a'

app - package_b fun_b . py

from app.package_a.fun_a import print_a
def print_b():
    print 'This is a function in dir package_b'
    print 'going to call a function in dir package_a'
    print '-'*30
    print_a()

main.py

from app.package_b import fun_b
fun_b.print_b()

如果你运行$ python main.py,它会返回:

This is a function in dir package_b
going to call a function in dir package_a
------------------------------
This is a function in dir package_a

Main.py执行如下操作 Fun_b.py从app.package_a。Fun_a import print_a

package_b文件夹中的文件使用package_a文件夹中的文件,这就是你想要的。对吧? ?

我发现将“PYTHONPATH”环境变量设置到顶部文件夹更容易:

bash$ export PYTHONPATH=/PATH/TO/APP

然后:

import sub1.func1
#...more import

当然,PYTHONPATH是“全局的”,但它还没有给我带来麻烦。

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到目标系统的脚本文件夹。

“Guido将包中运行的脚本视为反模式”(拒绝 pep - 3122)

我花了很多时间试图找到一个解决方案,阅读Stack Overflow上的相关文章,并对自己说“一定有更好的方法!”看起来没有。