您的位置:首页 > 编程语言 > Python开发

Python import语义

2015-11-28 10:58 609 查看

一. 前言
在python中,import是一个非常重要的语句。每当我们需要一个模块时,会使用import,这也是python如此强大,如此方便的原因。对于import的使用可以参考博客import,reload,__import__用法,而from...import...可以参考import迷宫 ,但是在使用import时有三个问题需要铭记或注意:
二. 实验

1. 在使用第一次import B时,会将B.py中模块中先执行一遍。

e.g. 将A.py和B.py放在同一文件夹中,结构1)为:----------------------------─test0A.pyB.py----------------------------A.py和B.py内容分别为:
# A.pyprint 'A.py'import B
# B.pydef foo():print 'B.py'foo()b = 'this is B.py'
并在test0目录下,执行A.py,输出的内容为:----------------------------A.pyB.py这是因为在”B.py”中,运行了foo()函数输出的。

2. 当运行某个模块时,只会将当前目录(递归)加载至sys.path中。

e.g. a) 将A.py和B.py放在如下结构中----------------------------─test1│ A.py│└─B_DIRB.pyinit.py----------------------------A.py和B.py的内容分别为:
# A.pyprint 'A.py'import B_DIR.B
# B.pydef foo():print 'B.py'foo()b = 'this is B.py'
并在test1目录下,执行A.py,输出的内容为:----------------------------A.pyB.pyb) 再将A.py和B.py放在如下结构3)中:----------------------------─test2│ B.py│└─A_DIRA.pyinit.py----------------------------A.py和B.py内容分别为:
# A.pyprint 'A.py'import B
# B.pydef foo():print 'B.py'foo()b = 'this is B.py'
则无论在任何目录下运行A.py,都会的得到结果:
----------------------------
Traceback (most recent call last):File “D:\Samples\test2\A_DIR\A.py”, line 3, inimport B_DIR.BImportError: No module named B_DIR.B那为什么a)和b)有两种不同的结果呢?原因很简单,其实在sys.modules[‘B’]为None,来看一下import加载module B的步骤:1. 检查 sys.modules[‘B’]是否存在;2. 如果存在直接跳至第4步;3. 如果不存在,则会在在sys.path中寻找中module B, 而sys.path中变量是一个列表,他的初始值来自这些位置:脚本所在的目录(或当前目录)。PYTHONPATH (一个包含目录名的列表,与 shell 变量PATH 的语法相同,如果 PYTHONPATH 未设置则来自于内置的默认值)。与安装相关的默认值。找到后加载模块,创建模块对象,以‘B’为key,对象为value,加入到sys.modules的dict中4. 在当前文件中,创建一个名为B的局部变量,并将B引用对象 sys.modules['B']。所以在目录结构3)中,这样运行A.py,那么sys.path中只会搜索A_DIR目录和安装路径下的module,所以就找不到module B,最终导致报错。若想要解决此类问题,有两种解决方案:方案1:在A.py中添加两行代码,修改为:
# A.pyimport syssys.path.append('D:/Samples/test2')print 'A.py'import B
方案2:A.py和B.py不作修改,在test2文件夹中新建C.py,即结构4)为:----------------------------─test2│ B.py│ C.py│└─A_DIRA.pyinit.py----------------------------C.py内容为:
# C.pyprint 'C.py'import A_DIR.A
运行C.py之后也可以将module B加入到sys.modules中。

3. 根据第2点import载入模块的步骤可以了解,如果没有特殊情况,注意每个module只会加载一次。

由此特别说一下这个例子:e.g. 有三个文件,文件结构为:----------------------------─test3A.pyB.pyC.py----------------------------内容分别是:
#A.pyprint 'A.py'import B
#B.pyprint 'B.py'import Cb = 'this is B.py'
#C.pyprint 'C.py'import Bprint B.b
在test3中运行A.py后,输出是:----------------------------A.pyB.pyC.pyTraceback (most recent call last):File “D:/Samples/test3/A.py”, line 2, inimport BFile “D:\Samples\test3\B.py”, line 2, inimport CFile “D:\Samples\test3\C.py”, line 3, inprint B.bAttributeError: ‘module’ object has no attribute ‘b’为什么最后一个print B.b会找不到b?梳理他们的执行步骤:
print 'A.py'(import B,load module B)print 'B.py'(import C, load module C)print 'C.py'(import B, already exist, don't load)print B.b ('module' object has no attribute 'b')b = 'this is B.py'
如果要避免这个问题,需要在C.py中reload(B)才能正确执行 print B.b。这个问题其实和
import sysreload(sys)sys.setdefaultencoding('utf-8')
是一样的,可以参考reload(sys) 的解释,这里不再赘述。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: