想象一下这个目录结构:

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文件夹中的文件,这就是你想要的。对吧? ?

其他回答

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

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)

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

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

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

从Python文档,

在Python 2.5中,你可以使用from __future__ import absolute_import指令将导入行为切换为绝对导入。这种绝对导入行为将成为未来版本(可能是Python 2.7)的默认设置。一旦绝对导入为默认值,import string将始终找到标准库的版本。建议用户开始尽可能多地使用绝对导入,因此最好在代码中从pkg导入字符串开始编写

正如@EvgeniSergeev在OP的注释中所说,你可以从.py文件中任意位置导入代码:

import imp

foo = imp.load_source('module.name', '/path/to/file.py')
foo.MyClass()

这是从这个SO答案中得来的。

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

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