一. 前言
在python中,import是一个非常重要的语句。每当我们需要一个模块时,会使用import,这也是python如此强大,如此方便的原因。对于import的使用可以参考博客import,reload,__import__用法,而from...import...可以参考import迷宫 ,但是在使用import时有三个问题需要铭记或注意:
二. 实验
一. 前言
在python中,import是一个非常重要的语句。每当我们需要一个模块时,会使用import,这也是python如此强大,如此方便的原因。对于import的使用可以参考博客import,reload,__import__用法,而from...import...可以参考import迷宫 ,但是在使用import时有三个问题需要铭记或注意:
二. 实验
1. 在使用第一次import B时,会将B.py中模块中先执行一遍。
e.g. 将A.py和B.py放在同一文件夹中,结构1)为:
----------------------------
─test0
A.py
B.py
----------------------------
A.py和B.py内容分别为:
# A.py
print 'A.py'
import B
# B.py
def foo():
print 'B.py'
foo()
b = 'this is B.py'
并在test0目录下,执行A.py,输出的内容为:
----------------------------
A.py
B.py
这是因为在”B.py”中,运行了foo()函数输出的。
2. 当运行某个模块时,只会将当前目录(递归)加载至sys.path中。
e.g. a) 将A.py和B.py放在如下结构中
----------------------------
─test1
│ A.py
│
└─B_DIR
B.py
init.py
----------------------------
A.py和B.py的内容分别为:
# A.py
print 'A.py'
import B_DIR.B
# B.py
def foo():
print 'B.py'
foo()
b = 'this is B.py'
并在test1目录下,执行A.py,输出的内容为:
----------------------------
A.py
B.py
b) 再将A.py和B.py放在如下结构3)中:
----------------------------
─test2
│ B.py
│
└─A_DIR
A.py
init.py
----------------------------
A.py和B.py内容分别为:
# A.py
print 'A.py'
import B
# B.py
def 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, in
import B_DIR.B
ImportError: 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 未设置则来自于内置的默认值)。
- 与安装相关的默认值。
4. 在当前文件中,创建一个名为B的局部变量,并将B引用对象 sys.modules['B']。
所以在目录结构3)中,这样运行A.py,那么sys.path中只会搜索A_DIR目录和安装路径下的module,所以就找不到module B,最终导致报错。若想要解决此类问题,有两种解决方案:
方案1:在A.py中添加两行代码,修改为:
# A.py
import sys
sys.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_DIR
A.py
init.py
----------------------------
C.py内容为:
# C.py
print 'C.py'
import A_DIR.A
运行C.py之后也可以将module B加入到sys.modules中。
3. 根据第2点import载入模块的步骤可以了解,如果没有特殊情况,注意每个module只会加载一次。
由此特别说一下这个例子:
e.g. 有三个文件,文件结构为:
----------------------------
─test3
A.py
B.py
C.py
----------------------------
内容分别是:
#A.py
print 'A.py'
import B
#B.py
print 'B.py'
import C
b = 'this is B.py'
#C.py
print 'C.py'
import B
print B.b
在test3中运行A.py后,输出是:
---------------------------- A.py
B.py
C.py
Traceback (most recent call last):
File “D:/Samples/test3/A.py”, line 2, in
import B
File “D:\Samples\test3\B.py”, line 2, in
import C
File “D:\Samples\test3\C.py”, line 3, in
print B.b
AttributeError: ‘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 sys
reload(sys)
sys.setdefaultencoding('utf-8')
是一样的,可以参考reload(sys) 的解释,这里不再赘述。