码迷,mamicode.com
首页 > 编程语言 > 详细

python的模块

时间:2018-03-23 15:26:23      阅读:188      评论:0      收藏:0      [点我收藏+]

标签:python 模块

参考:

https://www.cnblogs.com/bobo0609/p/6938012.html

https://docs.python.org/2/tutorial/modules.html


1.简介

在Python中,一个.py或者.pyc文件就称之为一个模块(Module)。即一个文件被看作一个独立的模块,一个模块也可以被看做是一个文件

.py:存放的是python源码

.pyc:存放的是python解释器对源码编译后的字节码


python把文件名去掉.py/.pyc后缀作为模块名,比如 os.py ,那么它的模块名就是 os


那么假设我们当前路径有个os.py,python怎么知道它的位置,并导入使用呢?

这里就涉及到python的模块搜索路径,它的搜索次序如下:

<1>当前路径

<2>PYTHONPATH变量自定义的路径(PYTHONPATH是系统自定义的环境变量,类似centos中的PATH)

<3>安装python时所定义的路径


有人会疑惑,python怎么知道我当前的路径在哪?


这是因为,python的程序包括一个顶层程序文件和其它的模块文件,这个顶层文件相当于程序执行的入口,类似shell脚本,我们执行脚本时必须写明绝对路劲或者切到对应路径去执行(这个时候路径就传递了),python也是同理


例子:


        [root@cqhdtest python_learn]# pwd
	/root/python_learn
	[root@cqhdtest python_learn]# cat getvalue.py
	#!/usr/local/anaconda2/bin/python
	x='Gx'
	y='Gy'
	z='Gz'
	def f1(x,y,z):
	    x='Ex'
	    z='Ez'
	    print x,y,z
	    def f2(x,y,z):
		x='Lx'
		print x,y,z
	    f2(x,y,z)
	f1(x,y,z)
	[root@cqhdtest python_learn]# cat index.py 
	import getvalue
	print x
	[root@cqhdtest python_learn]# python  index.py 
	Ex Gy Ez
	Lx Gy Ez
	Traceback (most recent call last):
	  File "index.py", line 2, in <module>
	    print x
	NameError: name 'x' is not defined



这里index.py作为程序入口导入了getvalue这个模块,显然,这里python找到了getvalue模块,因为程序执行到了print x,但是为什么会有"Ex Gy Ez"这些输出呢?


这是因为:python在首次导入模块(import 或者reload)的时候,会立即执行模块文件的顶层程序代码(不在函数内的代码,比如变量x'=Gx',函数定义def f1等,只要顶格写都会被执行),而位于函数主体内的代码直到函数被调用后才会执行,所以f1(x,y,z)函数被调用了,打印出了"Ex Gy Ez",而f1又自己调用了f2,所以f2函数打印了"Lx Gy Ez"


那么,既然模块有导入成功,x变量应该有定义,为何又提示“name 'x' is not defined”呢?


这是因为:为了避免大家的相同编程习惯导致各种变量覆盖(比如张三和李四被分派写两个不同的模块,张三习惯在他的变量中使用x,李四也习惯这样,那么当两个模块都被导入时,因为变量名相同,必然有一个的值会被覆盖掉),于是python在导入模块时,以模块名新建一个新的名称空间,在新的名称空间中创建变量。 简单地说,当导入getvalue模块的x变量的时候,此时x不再被当成x,而是被当成getvalue.x


例子:(接上例)

    [root@cqhdtest python_learn]# cat index.py 
	import getvalue
	print getvalue.x
	[root@cqhdtest python_learn]# python index.py 
	Ex Gy Ez
	Lx Gy Ez
	Gx


可以看见,此时的print 语句已经可以正常输出。


那么,如果我想随时随地可以导入getvalue模块,而又不想切到指定路径去,那么该怎么办呢?

这个时候,就要用到sys.path这个变量了


例子:


        In [2]: import sys

	In [3]: sys.path
	Out[3]: 
	['',
	 '/usr/local/anaconda2/bin',
	 '/usr/local/anaconda2/lib/python27.zip',
	 '/usr/local/anaconda2/lib/python2.7',
	 '/usr/local/anaconda2/lib/python2.7/plat-linux2',
	 '/usr/local/anaconda2/lib/python2.7/lib-tk',
	 '/usr/local/anaconda2/lib/python2.7/lib-old',
	 '/usr/local/anaconda2/lib/python2.7/lib-dynload',
	 '/usr/local/anaconda2/lib/python2.7/site-packages',
	 '/usr/local/anaconda2/lib/python2.7/site-packages/IPython/extensions',
	 '/root/.ipython']

	In [4]: sys.path.insert('/root/python_learn/')
	---------------------------------------------------------------------------
	TypeError                                 Traceback (most recent call last)
	<ipython-input-4-b628fd39dcd4> in <module>()
	----> 1 sys.path.insert('/root/python_learn/')

	TypeError: insert() takes exactly 2 arguments (1 given)

	In [5]: help (list.insert)


	In [6]: sys.path.insert(,'/root/python_learn/')
	  File "<ipython-input-6-c98c91c9451b>", line 1
	    sys.path.insert(,'/root/python_learn/')
	                    ^
	SyntaxError: invalid syntax


	In [7]: sys.path.insert(0,'/root/python_learn/')

	In [8]: sys.path
	Out[8]: 
	['/root/python_learn/',
	 '',
	 '/usr/local/anaconda2/bin',
	 '/usr/local/anaconda2/lib/python27.zip',
	 '/usr/local/anaconda2/lib/python2.7',
	 '/usr/local/anaconda2/lib/python2.7/plat-linux2',
	 '/usr/local/anaconda2/lib/python2.7/lib-tk',
	 '/usr/local/anaconda2/lib/python2.7/lib-old',
	 '/usr/local/anaconda2/lib/python2.7/lib-dynload',
	 '/usr/local/anaconda2/lib/python2.7/site-packages',
	 '/usr/local/anaconda2/lib/python2.7/site-packages/IPython/extensions',
	 '/root/.ipython']

	In [9]: import  getvalue
	Ex Gy Ez
	Lx Gy Ez

	In [10]: getvalue.x
	Out[10]: 'Gx'


python按照sys.path的顺序来查找模块,需要注意的是,insert方法需要两个参数,第一个是索引,这里使用0,放在第一位,优先查找我们自己的目录


如果我们再次import,python并不会再次执行顶层程序代码,而是简单地重载下内存中的对象


例子:

        In [29]: import getvalue

	In [30]: getvalue reload
	  File "<ipython-input-30-7cba10969034>", line 1
	    getvalue reload
	                  ^
	SyntaxError: invalid syntax


	In [31]: help(reload)


	In [32]: reload(getvalue)
	Ex Gy Ez
	Lx Gy Ez
	Out[32]: <module 'getvalue' from '/root/python_learn/getvalue.pyc'>



现在,模块加载没什么问题了,但是我觉得每次都要敲完整模块名getvalue,太烦人了,有没有什么办法呢?

这个时候就要用到import-as语句了


例子:


        In [33]: import getvalue as g

	In [34]: g.x
	Out[34]: 'Gx'



import xx  as x:把本来先创建名称空间名为getvlaue改成了g,所以调用就简单了,因为是修改所以此时getvalue这个名称空间是不存在的,所以不能用getvalue+'.'获取值


那么如果我比较任性,就想覆盖当前环境中的变量x呢?

这个时候就得用到from-import 语句了


例子:

        In [35]: from getvalue import x

	In [36]: x
	Out[36]: 'Gx'



from-import语句只会加载对应的属性或者方法到当前的名称空间,所以其他语句不会执行


所以python导入模块,大概分成以下几类:

import:直接导入

import Module as Module_alias:给变量取别名

from Module import Attribute/Method: 导入部分属性/方法

reload(Module):重新导入


既然作为模块,就该有作为模块的觉悟,一导入就瞎执行是会被clear的-_-!!

所以我们不该让模块中包含不该执行的语句,比如函数不该被调用。但是我又想这个模块文件有时作为程序顶层文件执行,有时作为模块被导入,那么有办法吗?


这个时候就可以用到内置属性__name__了


例子:


        [root@cqhdtest python_learn]# cp getvalue.py  New.py
	[root@cqhdtest python_learn]# vi New.py 
	[root@cqhdtest python_learn]# cat New.py 
	#!/usr/local/anaconda2/bin/python
	x='Gx'
	y='Gy'
	z='Gz'
	def f1(x,y,z):
	    x='Ex'
	    z='Ez'
	    print x,y,z
	    def f2(x,y,z):
		x='Lx'
		print x,y,z
	    f2(x,y,z)
	if __name__ == "__main__" :
	    f1(x,y,z)
	[root@cqhdtest python_learn]# python New.py 
	Ex Gy Ez
	Lx Gy Ez
	============================================
	In [6]: import New

	In [7]: New.x
	Out[7]: 'Gx'

	In [8]: reload(New)
	Out[8]: <module 'New' from 'New.pyc'>

	In [9]: New.__name__
	Out[9]: 'New'


这里的内置变量__name__,如果程序是顶层文件则为"__main__",否则为模块名


2.import的工作机制(摘抄自:https://www.cnblogs.com/bobo0609/p/6938012.html)


import语句导入指定的模块时会执行3个步骤

1. 找到模块文件:在模块搜索路径下搜索模块文件

  程序的主目录

  PYTHONPATH目录

  标准链接库目录


2.编译成字节码:文件导入时会编译,因此,顶层文件的.pyc字节码文件在内部使用后会被丢弃,只有被导入的文件才会留下.pyc文件

3.执行模块的代码来创建其所定义的对象:模块文件中的所有语句从头至尾依次执行,而此步骤中任何对变量名的赋值运算,都会产生所得到的模块文件的属性

注意:模块只在第一次导入时才会执行如上步骤,后续的导入操作只不过是提取内存中已加载的模块对象,reload()可用于重新加载模块


 


包: 用于将一组模块归并到一个目录中,此目录即为包,目录名即为包名


包是一个有层次的文件目录结构,它定义了一个由模块和子包组成的Python应用执行环境


基于包,Python在执行模块导入时可以指定模块的导入路径 import pack1.pack2.mod1


每个包内都必须有__init__.py文件, __init__.py 可包含python代码,但通常为空,仅用于扮演包初始化、替目录产生模块命名空间以及使用目录导入时实现from*行为的角色


python的模块

标签:python 模块

原文地址:http://blog.51cto.com/linzb/2090261

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!