1. 标准 import
Python 中全部加载到内存的模块都放在 sys.modules 。当 import 一个模块时首先会在这个列表中查找是否已经加载了此模块,若是加载了则只是将模块的名字加入到正在调用 import 的模块的 Local 名字空间中。若是没有加载则从 sys.path 目录中按照模块名称查找模块文件,模块能够是py、pyc、pyd,找到后将模块载入内存,并加到 sys.modules 中,并将名称导入到当前的 Local 名字空间。
一个模块不会重复载入。多个不一样的模块均可以用 import 引入同一个模块到本身的 Local 名字空间,其实背后的 PyModuleObject 对象只有一个。说一个容易忽略的问题:
import 只能导入模块,不能导入模块中的对象(类、函数、变量等)。例如:模块 A(A.py)中有个函数 getName,另外一个模块不能经过 import A.getName 将 getName导入到本模块,只能用 from A import getName。
2. 嵌套 import
1)顺序嵌套
例如:本模块导入 A 模块(import A),A 中又 import B,B 模块又能够 import 其余模块……
这中嵌套比较容易理解,须要注意的一点就是各个模块的 Local 名字空间是独立的。对于上面的例子,本模块 import A 以后本模块只能访问模块 A,不能访问模块 B 及其余模块。虽然模块 B 已经加载到内存了,若是访问还要再明确的在本模块中 import B。
2)循环嵌套
例如:文件[ A.py ]
from B import D
class C:pass
文件[ B.py ]
from A import C
class D:pass
为何执行 A 的时候不能加载 D 呢?
若是将 A.py 改成:import B 就能够了。
这是怎么回事呢?
RobertChen:这跟Python内部 import 的机制是有关的,具体到 from B import D,Python 内部会分红几个步骤:
(1)在 sys.modules 中查找符号 “B”
(2)若是符号 B 存在,则得到符号 B 对应的 module 对象。
从 <modult B> 的 __dict__ 中得到符号 “D” 对应的对象,若是 “D” 不存在,则抛出异常。
(3)若是符号 B 不存在,则建立一个新的 module 对象 <module B>,注意,此时,module 对象的 __dict__ 为空。
执行 B.py 中的表达式,填充 <module B> 的 __dict__。
从 <module B> 的 __dict__ 中得到 “D” 对应的对象,若是 “D” 不存在,则抛出异常。
因此这个例子的执行顺序以下:
一、执行 A.py 中的 from B import D 因为是执行的 python A.py,因此在 sys.modules 中并无 <module B> 存在, 首先为 B.py 建立一个 module 对象 (<module B>) , 注意,这时建立的这个 module 对象是空的,里边啥也没有, 在 Python 内部建立了这个 module 对象以后,就会解析执行 B.py,其目的是填充 <module B> 这个 __dict__。
二、执行 B.py中的from A import C 在执行B.py的过程当中,会碰到这一句, 首先检查sys.modules这个module缓存中是否已经存在<module A>了, 因为这时缓存尚未缓存<module A>, 因此相似的,Python内部会为A.py建立一个module对象(<module A>), 而后,一样地,执行A.py中的语句
三、再次执行A.py中的from B import D 这时,因为在第1步时,建立的<module B>对象已经缓存在了sys.modules中, 因此直接就获得了<module B>, 可是,注意,从整个过程来看,咱们知道,这时<module B>仍是一个空的对象,里面啥也没有, 因此从这个module中得到符号"D"的操做就会抛出异常。 若是这里只是import B,因为"B"这个符号在sys.modules中已经存在,因此是不会抛出异常的。
ZQ:图解
啄木鸟社区《import 迷宫》:
http://wiki.woodpecker.org.cn/moin/MiscItems/2008-11-25
3. 包 import
只要一个文件夹下面有个 __init__.py 文件,那么这个文件夹就能够看作是一个包。包导入的过程和模块的基本一致,只是导入包的时候会执行此包目录下的 __init__.py 而不是模块里面的语句了。另外,若是只是单纯的导入包,而包的 __init__.py 中又没有明确的其余初始化操做,那么此包下面的模块是不会自动导入的。
例如:
有下面的包结构:
PA
|---- __init__.py
|---- wave.py
|---- PB1
|---- __init__.py
|---- pb1_m.py
|---- PB2
|---- __init__.py
|---- pb2_m.py
有以下程序:
import sys
import PA.wave
#1
import PA.PB1
#2
import PA.PB1.pb1_m as m1
#3
import PA.PB2.pb2_m
#4
PA.wave.getName()
#5
m1.getName()
#6
PA.PB.pb2_m.getName()
#7
1) 当执行 #1 后,sys.modules 会同时存在 PA、PA.wave 两个模块,此时能够调用 PA.wave 的任何类或函数了。但不能调用 PA.PB1(2) 下的任何模块。当前 Local 中有了 PA 名字。
2) 当执行 #2 后,只是将 PA.PB1 载入内存,sys.modules 中会有 PA、 PA.wave、PA.PB1 三个模块,可是 PA.PB1 下的任何模块都没有自动载入内存,此时若是直接执行 PA.PB1.pb1_m.getName() 则会出错,由于 PA.PB1 中并无 pb1_m 。当前 Local 中仍是只有 PA 名字,并无 PA.PB1 名 字。
3) 当执行 #3 后,会将 PA.PB1 下的 pb1_m 载入内存,sys.modules 中会有 PA、PA.wave、PA.PB一、PA.PB1.pb1_m 四个模块,此时能够执行 PA.PB1.pb1_m.getName() 了。因为使用了 as,当前 Local中除了 PA 名字,另外添加了 m1 做为 PA.PB1.pb1_m 的别名。
4) 当执行 #4 后,会将 PA.PB二、PA.PB2.pb2_m 载入内存,sys.modules 中会有 PA、PA.wave、PA.PB一、PA.PB1.pb1_m、PA.PB二、PA.PB2.pb2_m 六个模块。当前 Local 中仍是只有 PA、m1。
下面的 #5,#6,#7 都是能够正确运行的。
注意的是:若是 PA.PB2.pb2_m 想导入 PA.PB1.pb1_m、PA.wave 是能够直接成功的。最好是采用明确的导入路径,对于 ./.. 相对导入路径仍是不推荐用。
原文:
http://blog.csdn.net/zbyufei/article/details/5894645
======================================
from module import *把module中的成员所有导到了当前的global namespace,访问起来就比较方便了。固然,python style通常不建议这么作,由于可能引发name conflict。html
但还有另一个问题 - 你觉得你修改了某个变量,其实,被from module import *后的那个并无被更新,很是危险,由于程序有可能还能够正常运行, 只不过结果错了,到了production才被发现就比较惨了。python
举个例子:缓存
你定义了一些变量在base模块中:函数
# reference data type
class Demo:
def __init__(self, name):
self.name = name
demo = Demo('Demo')
# primitive type
foo = 1
而后在一个模块中用from module import 的方式读它:post
from base import *
def read():
print 'reference data id: ' + str(id(demo))
print 'reference data value : ' + demo.name
print 'primitive data id: ' + str(id(foo))
print 'primitive data value: ' + str(foo)
在另一个模块中写它:ui
import base
def write():
print "\nOriginal:"
print "Original reference data id: " + str(id(base.demo))
base.demo.name = "Updated Demo" # this will reflect that change
#base.demo = base.Demo("Updated Demo") # this won't relfect the change
print "Original data id: " + str(id(base.foo))
base.foo = 1000
print "Original data id after assignment: " + str(id(base.foo))
而后先写,后读,看写的内容是否有效:this
import read
import write
print "before write"
read.read()
write.write()
print "\nafter write"
read.read()
结论是没有,缘由是:url
- 当你用from module import时,实际上是copy了一份reference或者pointer,指向一分内存,var和module.var都指向同一分内存
- 当你修改module.var时,其实你是让它指向了另一分内存,此时var和module.var指向的是不一样的内存
- 因此,虽然module.var的值变了,var仍是指向原来那分内存,原来的值
这个对于object,比较容易理解,你能够直接修改object里的值,这个是有效的,可是当你指向另一个object时就无效了。 对于primitive类型来说,其实也是一个道理,由于每次赋值,都是让其指向一个不一样的内存地址,而不是inplace修改已有的那分内存 - 这个很容易验证:spa
In [1]: a = 10
In [2]: id(a)
Out[2]: 20429204
In [3]: a = 100
In [4]: id(a)
Out[4]: 20430108
因此,建议是除非是一个quick and dirty的脚本,不然不要使用from module import *!.net