模块

---恢复内容开始---

什么是模块

模块就是python代码的文件

为什么要有模块

某些代码需要在不同的文件中重复使用,代码可读性差,写代码困难大

 

导入模块时做的事

执行python解释器时,就已经在内存中加载了一些内置模块了

import sys
print(sys.modules)
{'builtins': <module 'builtins' (built-in)>, 'sys': <module 'sys' (built-in)>, '_frozen_importlib': <module '_frozen_importlib' (frozen)>, '_imp': <module '_imp' (built-in)>, '_warnings': <module '_warnings' (built-in)>, '_thread': <module '_thread' (built-in)>, '_weakref': <module '_weakref' (built-in)>, '_frozen_importlib_external': <module '_frozen_importlib_external' (frozen)>, '_io': <module 'io' (built-in)>, 'marshal': <module 'marshal' (built-in)>, 'nt': <module 'nt' (built-in)>, 'winreg': <module 'winreg' (built-in)>, 'zipimport': <module 'zipimport' (built-in)>, 'encodings': <module 'encodings' from 'C:\\Python36\\lib\\encodings\\__init__.py'>, 'codecs': <module 'codecs' from 'C:\\Python36\\lib\\codecs.py'>, '_codecs': <module '_codecs' (built-in)>, 'encodings.aliases': <module 'encodings.aliases' from 'C:\\Python36\\lib\\encodings\\aliases.py'>, 'encodings.utf_8': <module 'encodings.utf_8' from 'C:\\Python36\\lib\\encodings\\utf_8.py'>, '_signal': <module '_signal' (built-in)>, '__main__': <module '__main__' (built-in)>, 'encodings.latin_1': <module 'encodings.latin_1' from 'C:\\Python36\\lib\\encodings\\latin_1.py'>, 'io': <module 'io' from 'C:\\Python36\\lib\\io.py'>, 'abc': <module 'abc' from 'C:\\Python36\\lib\\abc.py'>, '_weakrefset': <module '_weakrefset' from 'C:\\Python36\\lib\\_weakrefset.py'>, 'site': <module 'site' from 'C:\\Python36\\lib\\site.py'>, 'os': <module 'os' from 'C:\\Python36\\lib\\os.py'>, 'errno': <module 'errno' (built-in)>, 'stat': <module 'stat' from 'C:\\Python36\\lib\\stat.py'>, '_stat': <module '_stat' (built-in)>, 'ntpath': <module 'ntpath' from 'C:\\Python36\\lib\\ntpath.py'>, 'genericpath': <module 'genericpath' from 'C:\\Python36\\lib\\genericpath.py'>, 'os.path': <module 'ntpath' from 'C:\\Python36\\lib\\ntpath.py'>, '_collections_abc': <module '_collections_abc' from 'C:\\Python36\\lib\\_collections_abc.py'>, '_sitebuiltins': <module '_sitebuiltins' from 'C:\\Python36\\lib\\_sitebuiltins.py'>, 'sysconfig': <module 'sysconfig' from 'C:\\Python36\\lib\\sysconfig.py'>, 'atexit': <module 'atexit' (built-in)>}
运行python文件时加载的模块

在第一次导入某个模块时,会先检查该模块是否已经被加载到内存中(当前执行文件的名称空间对应的内存),如果有直接引用。

如果没找到就从sys.path给出的目录列表中依次寻找文件。

所以模块的查找顺序是:内存中加载的>sys.path路径中包含的模块

所以给模起名时不要起内置模块的名字,比如re模块,re模块虽然是内置模块,但却没有被加载到内存中,当你在运行文件的目录中创建一个名为re的python文件时,在调用就会调用到你创建的名为re的python文件

导入模块时,如果模块不存在sys.modules,才从sys.path给的路径中去查找

sys.path决定某个模块能不能被找到

import sys
print(sys.path)
#['', 'C:\\Python36\\python36.zip', 'C:\\Python36\\DLLs', 'C:\\Python36\\lib', 'C:\\Python36', 'C:\\Python36\\lib\\site-packages']

第一个位置就是运行python的位置

当导入模块时,按照这个顺序从前往后依次查找

在初始化后,python程序可以修改sys.path,路径放到前面的优先于标准库被加载

import sys
sys.path.append('/a/b/c/d')
sys.path.insert(0,'/x/y/z') #排在前的目录,优先被搜索

导入模块时,会创建名为模块名的一个命名空间,在这个命名空间中执行代码

 

模块的导入

模块导入的几种方法

import 模块名

import os
#模块名.函数名()就可执行模块中的函数
#模块名.函数名就可调用模块中的变量

#使用import方式导入的模块中的内容和自己文件中的内容不会冲突。
#因为模块中的变量和函数存在这个模块开辟的局部命名空间中

import 模块名,模块名,模块名

import os,sys,re
#一次导入多个模块,但是一般不这么用
导入时,先导入内置模块
再倒入拓展模块
最后导入自定义模块,各种模块用空行隔开
import os
import sys
import re
#上面是内置模块
import django
#上面是拓展模块
#最后是自定义模块


import 模块名 as 新名字

给模块重命名,重命名之后之前的名字就失效了,新名字可以直接使用

#当模块名十分复杂时,可以重命名
#import 十分复杂的函数名 as a
#在使用时就用a.变量名。十分复杂的函数名就没用了

#当导入的模块和文件中的变量重名的时候

#当兼容多个模块的操作相同的时候
举个栗子
mysql数据库和oracle数据库的操作相同
只需要在前面判断,然后改成相同的名字,就可以不用改动下面的内容
# if 是mysql数据库: 
#     import mysql as db
# elif 是oracle数据库:
#     import oracle as db
# db.open
# db.write

 form 模块名 import 变量名 

# from import的用法 会直接将导入的内容放在全局
# 如果有同名,就会发生覆盖

# 但是模块中用到的变量和模块中方法是一种绑定关系
#即使你覆盖了导入的变量,但是你在调用导入的方法时,方法调用这个变量,依然是去调用模块中的这个变量

使用form import 来导入多个值和改名

from 模块名 import 变量名 as 新名字,变量名 as 新名字
#导入内容用逗号隔开

使用form import导入模块中的全部内容

from 模块名 import *
__all__=["",""]
#当使用这种模式时,在模块中可以设置__all__变量来限制
#默认是没有这个变量,可以导入模块中的全部名字

#设定后只能导入__all__中的名字

把模块当作脚本执行

我们可以通过模块的全局变量__name__来查看模块名:
当做脚本运行:
__name__ 等于'__main__'

当做模块导入:
__name__= 模块名

作用:用来控制.py文件在不同的应用场景下执行不同的逻辑
if __name__ == '__main__':

print(__name__)
#当在模块内打印__name__时,结果是__main__
#当这个拥有这个代码的模块被导入时,打印的就是模块名。

#可以在模块中设置
if __name__=="__main__":
#下面是在模块中执行的内容
#如果导入这个模块,则其中的内容就不会执行

编译python--导入模块后,会生成一个pyc文件,就是python的编译文件

为了提高加载模块的速度,强调强调强调:提高的是加载速度而绝非运行速度。python解释器会在__pycache__目录中下缓存每个模块编译后的版本,格式为:module.version.pyc。通常会包含python的版本号。例如,在CPython3.3版本下,my_module.py模块会被缓存成__pycache__/my_module.cpython-33.pyc。这种命名规范保证了编译后的结果多版本共存。

 

Python检查源文件的修改时间与编译的版本进行对比,如果过期就需要重新编译。这是完全自动的过程。并且编译的模块是平台独立的,所以相同的库可以在不同的架构的系统之间共享,即pyc使一种跨平台的字节码,类似于JAVA火.NET,是由python虚拟机来执行的,但是pyc的内容跟python的版本相关,不同的版本编译后的pyc文件不同,2.5编译的pyc文件不能到3.5上执行,并且pyc文件是可以反编译的,因而它的出现仅仅是用来提升模块的加载速度的。

 

python解释器在以下两种情况下不检测缓存
  1 如果是在命令行中被直接导入模块,则按照这种方式,每次导入都会重新编译,并且不会存储编译后的结果(python3.3以前的版本应该是这样)

python -m my_module.py

  2 如果源文件不存在,那么缓存的结果也不会被使用,如果想在没有源文件的情况下来使用编译后的结果,则编译后的结果必须在源目录下 

提示:

1.模块名区分大小写,foo.py与FOO.py代表的是两个模块

2.你可以使用-O或者-OO转换python命令来减少编译模块的大小

-O转换会帮你去掉assert语句
-OO转换会帮你去掉assert语句和__doc__文档字符串
由于一些程序可能依赖于assert语句或文档字符串,你应该在在确认需要的情况下使用这些选项。
了解

3.在速度上从.pyc文件中读指令来执行不会比从.py文件中读指令执行更快,只有在模块被加载时,.pyc文件才是更快的

4.只有使用import语句是才将文件自动编译为.pyc文件,在命令行或标准输入中指定运行脚本则不会生成这类文件,因而我们可以使用compieall模块为一个目录中的所有模块创建.pyc文件

 

posted @ 2017-11-16 16:54  瓜田月夜  阅读(97)  评论(0)    收藏  举报