Python中意外的相对导入行为

Roc*_*man 7 python python-import

今天我遇到了一个非常令人惊讶的相对进口行为(不幸的是,将我的头发拉了近4个小时后).

我一直认为,如果你在一个名为"package"的包中的模块名称"module_a.py"中有"A类",你可以等效地使用它们:

from package.module_a import ClassA
Run Code Online (Sandbox Code Playgroud)

要么

from module_a import ClassA
Run Code Online (Sandbox Code Playgroud)

只要您从"包"中的模块导入.我明白这是相对重要的.

直到今天,当我需要检查A类对象的实例时,我从未遇到任何问题,我很惊讶地发现了一种非常不寻常的行为.

考虑以下:

包/ module_a.py

class ClassA(object):
    pass

def check_from_module_a(obj):
    print 'from module_a'
    print '-------------'
    print 'class is:', ClassA
    print 'object is', type(obj) 
    print 'is obj a ClassA:', isinstance(obj, ClassA)
Run Code Online (Sandbox Code Playgroud)

包/ module_b.py

from package.module_a import ClassA
from module_a import check_from_module_a

a = ClassA()
check_from_module_a(a)

print ' '
print 'from module_b'
print '-------------'
print 'class is:', ClassA
print 'object is', type(a) 
print 'is obj a ClassA:', isinstance(a, ClassA)
Run Code Online (Sandbox Code Playgroud)

现在执行module_b.py时,你得到:

from module_a
-------------
class is: <class 'module_a.ClassA'>
object is <class 'package.module_a.ClassA'>
is obj a ClassA: False

from module_b
-------------
class is: <class 'package.module_a.ClassA'>
object is <class 'package.module_a.ClassA'>
is obj a ClassA: True
Run Code Online (Sandbox Code Playgroud)

我已经遵循逻辑,现在看看为什么会发生这种情况 - 这并不是很明显,因为我认为ClassA的绑定是相同的,无论绝对或相对导入.这给我带来了一个非常讨厌的错误,很难隔离.

我的问题:

  1. 这是预期的行为吗?

  2. 如果这是它应该工作的合理方式 - 那么我不清楚为什么我会使用相对导入,如果它们与绝对导入不兼容(在上面意义上).这里有一个很好的解释我错过了吗?

  3. 我总是假设当子包结构可能被移动时,相对导入在大型重构中提供了额外的容易性.这是相对进口的主要好处吗?

Kei*_*ith 4

由于隐式相对导入引起了问题,因此它们已在 Python 3 中被删除。您通常不会获得它们的预期行为。请参阅PEP-328进行讨论。如果您定义的子包名称与基本(库存)模块同名,则尤其如此。