Python 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 未设置则来自于内置的默认值)。 
  • 与安装相关的默认值。 
找到后加载模块,创建模块对象,以‘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.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) 的解释,这里不再赘述。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值