原文:http://effbot.org/zone/import-confusion.htm
import 和 from-import 对于Python新手经常带来严重的混淆,不过相信大家一旦清楚它们的实现机理后就不会对使用他们有任何困惑了。 这篇文章将努力理清import和from-import 相关的一切。
Python提供至少三种方式来import modules。使用import、from或者内置的__import__function,篇幅所限本文不讨论其他的非主流方式。 下面是这几种方式的实现原理:
简而言之:尽量用import。 以下几处情形例外:
当Python导入module时,它首先检查module注册表(sys.modules)确认是否该module已经被导入过,如果存在就使用已导入的module代替它。 否则,Python将执行以下步骤:
这意味着导入一个已经加载的module性能消耗是非常小的,Python只需要在dictionary中查找下module的名字就可以了。
如果你将一个module作为脚本运行,即直接将其名称给编译器而非导入它,那它将以名称__main__加载。 如果稍后在程序中加载同一个module,它将被重新加载并以其真实的名称重新执行,所以如果不细心的话可能会做两次同样的事。
在Python中,像def、class和import之类的语句都是声明。 module在导入时被执行,但新的函数和类并不会添加到module的命名空间中直到执行def或class进行声明,这在循环导入会有很明显的影响。 比如module X导入module Y并定义一个函数spam:
# module X
import Y
def spam():
print "function in module x"
如果从主程序中导入X,Python将加载X的代码并执行它。当Python到import Y这一行声明时,它加载Y的代码并转而执行Y的代码。 此时,Python已经在sys.modules中加载了X和Y。但X还不包含任何东西,def spam这行声明还未执行。 现在如果Y导入X(出现循环导入),它将得到一个指向空module X对象的引用,但如果试图调用函数X.spam将会失败,因为此时虽然存在X但并不存在X.spam:
# module Y
from X import spam # doesn't work: spam isn't defined yet!
这个问题和使用from-import无关,即使换用import也会如此:
# module Y
import X
X.spam() # doesn't work either: spam isn't defined yet!
解决的方法就是重构代码来避免循环导入,通常可以通过将部分内容拆分到单独的module来解决。这种解决方式类似于C++中解决循环引用时使用前置声明将声明和定义分离的方法,即将冲突的执行代码分拆到其他文件。 或者将import移到module的末尾,比如上面的例子如果将import Y移到module X的末尾就可以一切正常了,但其实并不总奏效,万一X.spam使用过Y就又出错了。