首页 > 代码库 > Python包和模块的导入问题

Python包和模块的导入问题

模块——代码封装 
模块是Python组织代码的基本方式。Python的脚本都是用扩展名为py的文本文件保存,一个脚本可以单独运行,也可以导入另一个脚本中运行,当脚本被导入运行时,我们将其称为模块(module)。就是说,我们在python里写的所有代码文件都可以叫模块。 
导入的时候,模块名与脚本的文件名相同,例如我们编写了一个名为items.py 的脚本,则在另外一个脚本中用import item语句来导入它。 
windows环境下在python中查看安装有哪些模块

>>> import sys >>> sys.modules #windows环境下,导入模块方式: >>> import os >>> os.getcwd() ‘D:\\Python33‘ >>> os.chdir (‘F:\eclipse\workspace\learn\extend‘) >>> os.getcwd() ‘F:\\eclipse\\workspace\\learn\\extend‘ >>> import calculator 0.5 #首先定位python的工作目录os.getcwd() #然后改为当前工作目录os.chdir (‘F:\eclipse\workspace\learn\extend‘) #在F:\eclipse\workspace\learn\extend这个目录下有一个之前写好的计算器文件名为calculator.py #直接导入用import calculator就可以得出结果了。 #如果我导入上节课做的fibonacci螺旋递归代码 #那么一样进入用户交互 >>> import fibonacci3 请输入Fibonacci螺旋层数:8 注意:两个数字不能同时为0! 第一个数字2.6 第二个数字-2.12 2.60 -2.12 0.48 -1.64 -1.16 -2.80 -3.96 -6.76 >>>

那么在编辑器里这样写

print(‘这是在运行导入的模块‘) import fibonacci3 #运行结果:  这是在运行导入的模块 请输入Fibonacci螺旋层数:6 注意:两个数字不能同时为0! 第一个数字2.2 第二个数字0.95 2.20 0.95 3.15 4.10 7.25 11.35
print(‘这是在运行导入的模块‘) import calculator3 #运行结果:  这是在运行导入的模块 1.5

那么看看calculator3.py的源代码:

from __future__ import division def f(x,o,y): print({‘+‘ : x+y, ‘-‘ : x-y,‘*‘ : x*y, ‘/‘ : x/y}.get(o)) f(3,‘/‘,2)

里面已经做了一个运算,所以import的时候直接是输出结果。如果我们把运算去掉也就是剩下这段代码

from __future__ import division def f(x,o,y): print({‘+‘ : x+y, ‘-‘ : x-y,‘*‘ : x*y, ‘/‘ : x/y}.get(o))

那么我们再次导入这个模块的时候是只剩下函数,需要额外调用。调用方法为(新建一个mol.py文件):

print(‘这是在运行导入的模块‘) import calculator3 calculator3.f(3, ‘/‘, 2) #注意,调用模块函数的方法是 模块名.函数名(参数值) #运行结果  这是在运行导入的模块 1.5

这里有个问题,如果我的模块里包含了函数赋值计算,如:

from __future__ import division def f(x,o,y): print({‘+‘ : x+y, ‘-‘ : x-y,‘*‘ : x*y, ‘/‘ : x/y}.get(o)) f(3,‘*‘,2)

那么我再次运行mol.py文件时会出现两个结果:


这是在运行导入的模块 6 1.5

  第一个结果 6 是模块自身的运算结果,第二个1.5是在mol.py里调用模块函数的运算结果。 
在实际应用中,有两种情况考虑。 
第一是直接执行模块文件的话,里面的运算是需要执行的。 
第二是如果是被别人所调用的话,那么模块里的运算程序是不需要执行的 
解决方法需要借助一个内置属性,现在在calculator3.py里加一行:


from __future__ import division def f(x,o,y): print({‘+‘ : x+y, ‘-‘ : x-y,‘*‘ : x*y, ‘/‘ : x/y}.get(o)) print(__name__) #这个__name__就是内置函数,__name__的值会随着调用的对象不同而变化 #如果我们直接运行: __main__ #这是这个文件的对象名,大概意思是指我们现在调用的是主体程序(按着教程猜的) #我们在mol.py里调用 print(‘这是在运行导入的模块‘) import calculator3 calculator3.f(3, ‘/‘, 2) #运行结果:  这是在运行导入的模块 calculator3 #这里__name__的值变成了文件名

1.5

 

因此,可以在calculator3.py里加一个判断,当__name__ ==__main__的时候执行源文件的运算程序, 
否则运行模块调用的函数赋值运算。

from __future__ import division def f(x,o,y): print({‘+‘ : x+y, ‘-‘ : x-y,‘*‘ : x*y, ‘/‘ : x/y}.get(o)) if __name__ == ‘__main__‘: f(3,‘*‘,2) #那么直接运行calculator3.py的时候会做 f(3,‘*‘,2) 的运算,而在mol.py里运行则不会运算: print(‘这是在运行导入的模块‘) import calculator3 calculator3.f(3, ‘/‘, 2) #运行结果: 这是在运行导入的模块 1.5

导入模块的时候有顺序限制,一般先从当前目录下查找模块文件,然后再从内置模块中查找 
这句怎么理解? 
string模块是内置模块,如果我在当前目录新建了一个叫string.py的文件,导入之后如果想使用string内置函数的话,那么程序会先在目录下查找string这个模块,这里新建的string.py会被导入,执行string内置函数的话就会出错。因此要使用string模块的话必须把新建的那个string.py文件删除,同时还得删除刚才导入时生成的一个叫string.pyc的文件。才能正确使用string这个内置模块

包 
Python的模块可以按目录组织为包 
创建一个包的步骤是: 
1.建立一个名字为包名字的文件夹, 
2.在该文件夹下创建一个__init__.py文件, 
3.根据需要在该文件夹下存放脚本文件、已编译扩展及子包 
4. import pack.m1, pack.m2, pack.m3


示范:新建一个pack.py文件,假如我们要想重复使用calculator3.py里的函数运算,那么可以在calculator3.py所在目录下新建一个文件夹,假如命名为bag,在bag文件夹里新建一个__init__.py文件(必须有),内容可以为空,把需要导入的calculator3.py文件复制进去。那么这个bag文件夹就可以称之为python包。注意,调用模块的py文件不能在包里,如这里新建的pack.py不能放在bag里,否则会报错。 
文件结构如图: 
QQ图片20140302212938

print(‘这是在运行导入的python包‘) import bag.calculator3 #注意格式,包名字.模块名 bag.calculator3.f(3, ‘/‘, 2) #调用函数时候 包名字.模块名.函数名(参数值) #运行结果: 这是在运行导入的python包 1.5

小结: 
模块导入有import,import as,from import等几种方法。具体区别参考: 
http://www.cnblogs.com/allenblogs/archive/2011/11/15/2055149.html 


Python包和模块的导入问题