模块
什么是模块
自我包含并且有组织的代码片断就是模块( module )
模块是Pyhon最高级别的程序组织单元,它将程序代码和数据封装起来以便重用。实际的角度,模块往往对应Python程序文件。
每个文件都是一个模块,并且模块导入其他模块之后就可以使用导入模块定义的变量名。模块可以由两个语句和一个重要的内置函数进行处理。
import: 使客户端(导入者)以一个整体获取一个模块。
from:容许客户端从一个模块文件中获取特定的变量名。
reload:在不中止Python程序的情况下,提供了一个重新载入模块文件代码的方法。
模块搜索
导入模块时,不带模块的后缀名,比如.py
Python搜索模块的路径:
-
程序的主目录
-
PTYHONPATH目录(如果已经进行了设置)
-
标准连接库目录(一般在/usr/local/lib/python2.X/)
-
、任何的.pth文件的内容(如果存在的话).新功能,允许用户把有效果的目录添加到模块搜索路径中去
.pth后缀的文本文件中一行一行的地列出目录。
这四个组建组合起来就变成了sys.path了,
>>> import sys
>>> sys.path
导入时,Python会自动由左到右搜索这个列表中每个目录
模块的创建和使用
创建模块
后缀.py文本文件,模块顶层(模块内的全局变量、类和函数的声明)指定的所有变量名都会变成其属性。
定义一个module.py模块
from语句
from将获取(复制)模块特定变量名
from 模块名 import 需要复制的属性
from 模块名 import 需要复制的属性 as 新的属性名
from会把变量名赋值到另一个作用域,所以它就可以让我们直接在脚本中使用复制后的变量名,而不是通过模块
from * 语句
from 模块名 import *
取得模块顶层所有赋了值的变量名的拷贝
模块只导入一次,因为该操作开销大
import和from是赋值语句,是可执行的语句,可以嵌套到if ,def语句中
和def一样import和from都是隐性赋值语句
import将整个模块对象赋值给一个变量名from将一个或多个变量名赋值给另一个模块中同名的对象
**from as将一个或者多个变量名赋值给另一个模块中不同名的对象
>>> from module import name,age复制多个变量名时要用逗号隔开
>>> name,age
('diege', 18)
>>> from module import name as myname,age as myage复制多个变量名并改变需时需要用逗号隔开多个as
from语句的潜在陷阱
from让变量位置更隐秘和模糊。
from语句有破坏命名空间的潜质。如果from导入变量,而那些变量碰巧和作用域中现有的变量同名,变量就会被悄悄地覆盖掉。
使用简单的import时就不会存在这个问题。因为必须通过模块名才能获取其内容。
真正务实的建议就是:简单模块一般倾向于使用import而不是from。
多数的from语句是用于明确列举出想要的变量,而且限制在每个文件中只用一次from *形式。
何时使用inport
当使用两个不同的模块内定义的相同变量名时,才真的必须使用import.用from会覆盖。
模块导入的特征
-
载入时执行模块,也就是导入模块的顶层代码将会被执行,通常包括该模块内全局变量、类和函数的声明。我们尽可能多的把代码封装到函数中,这是良好的模块编程习惯。
-
一个模块可被导入(import)多次,但是只加载(load)一次.
关于reload内置函数
模块程序代码默认值对每个过程执行一次,要强制使模块代码重新载入并重新运算需要使用reload内置函数。
reload是函数,import是语句。两个语法不一样。
reload()之前需得import过一次
模块内建函数
__import__():导入模块的函数
import语句实际上调用__import__()函数
如果我们有一个testa.py文件,我们可以用module=__import__('testa')来导入它。这样可以用module.属性来使用testa.py中的属性
模块命名空间
-
一个名称空间就是从名称到对象的关系隐射集合。
-
模块最好理解为变量名的封装,简而言之,模块就是命名空间(变量名建立所在的场所),而存在于模块之内的变量名就是模块对象的属性。
-
文件生成命名空间
-
模块语句会在首次导入时执行。
-
顶层的赋值语句会创建模块属性(文件顶层不在的def和class之内的,但def和class隐性创建的变量名也属于模块属性)。赋值的变量名会存储在模块的命名空间内。
模块的命名空间能通过属性__dict__(module.__dict__)或dir(module)获取
由于导入而建立的模块的命名空间是字典,可通过模块对象相关联的内置__dict__属性读取。
dir函数查看,大至与对象的__dict__属性的键排序后的列表相等,但是它还包含了类继承的变量名。
模块是一个独立的作用域。
包
包是一个有层次的文件目录结构, 它定义了一个由模块和子包组成的 Python 应用程序执行环境。Python 1.5 加入了包, 用来帮助解决如下问题:
-
为平坦的名称空间加入有层次的组织结构
-
允许程序员把有联系的模块组合到一起
-
允许分发者使用目录结构而不是一大堆混乱的文件
-
帮助解决有冲突的模块名称
import web.child_web.demo
from web.child_web.demo import x
.号路径相当于机器上目录层次的路径
Web在容器目录src中,src这个目录可以在python模块搜索路径中找到。
关于__init__.py
如果选择使用包导入,那就必须遵循一条约束:包导入语句的路径的每个目录内部都必须有__init__.py这个文件,否则导入包会失败。
Web和child_web必须包含有__init__.py,而src是容器目录,不需要__init__.py文件,因为本身不在import语句中。
__init__.py文件可以包含程序代码,也可以是空的。更通常情况下,__init__.py文件扮演了包初始化的挂钩替目录产生模块命名空间以及用目录导入实现from 行为的角色。
__init__.py文件可以包含程序代码,也可以是空的。更通常情况下,__init__.py文件扮演了包初始化的挂钩替目录产生模块命名空间以及用目录导入实现from 行为的角色。
包初始化:
首次导入某个目录时,会自动执行该目录下__init__.py文件中所有程序代码。
所以这个文件就是放置包内文件所需初始化的代码的场所。可以使用其初始化文件,创建所需的数据文件,连接数据库等。
from 语句的行为:
作为一个高级功能,可以在__init__.py文件中使用__all__列表来定义目录以form 语句形式导入时,需要导出什么。__all__列表是指出当包(目录—)名称使用`from `的时候,应该导入的子模块名称清单。
eg:
常见的第三方扩展都是以包目录形式发布给用户,而不是单纯的模块列表。
这样就可以通过路径来导入
from mod_python.apache import CallBack
从mod_python包(一个安装子目录)的apache模块取出一些变量
模块陷阱
-
在导入时,模块文件顶层的程序代码(不在函数内)一旦python运行,就会立刻执行。因此,该语句是无法引用文件后面位置赋值的变量名。
-
位于函数主体内的代码知道函数被调用后才会运行。因为函数内的变量名在函数实际执行前都不会解析,通常可以引用文件内任意地方的变量。在顶层程序内混用def不尽难读,也造成了对语句顺序的依赖性。作为一条原则,如果需要把立即执行的代码和def一起混用,就要把def放在文件前面,把顶层代码放在后面。这样的话,你的函数在使用的代码运行时,可以保证他们都已定义并赋值过了。
2. 通过变量名字符串导入模块的方法import或from语句内的模块名是"硬编码"的变量名。
3. 这里python会试着导入文件x.py为了避免发生这样的问题,通常的做法就是把import语句构造成python代码的字符串,再传给exec语句执行:
>>> modname='string'
>>> exec "import "+modname
exec语句以及和他类似eval会编译一段字符串代码,将其传给Python解析器来执行。
from语句其实是在导入者的作用域内对变量名的赋值语句,也就是变量名拷贝运算,而不是变量名的别名机制。它的实现和python所有赋值运算都一样,微妙之处在于,共享对象的代码存在于不同的文件中。然后,我们使用import获得了整个模块,然后赋值某个点号运算的变量名,就会修改导入的模块中的变量名。点号运算把python定向到了模块对象,而不是赋值模块中对象。
reload中引用模块得通过import至少将其加载一次:
不要from导入之后reload
当重载一个模块时,Python只会重载那个模块的文件,不会自动重载该文件重载嘶碰巧还要导入的模块。
不要在递归导入中使用 from。