模块就是一组功能的集合体,咱们的程序能够导入模块来复用模块里的功能。每个 Python 脚本.py文件均可以被当成是一个模块。模块以磁盘文件的形式存在。当一个模块变得过大,而且驱动了太多功能的话,就应该考虑拆一些代码出来另外建一个模块。模块里的代码能够是一段直接执行的脚本,也能够是一堆相似库函数的代码,从而能够被别的模块导 入(import)调用。模块能够包含直接运行的代码块、类定义、 函数定义或这几者的组合。html
模块分类:Python标准库模块、Python第三方模块、应用程序自定义模块。python
Python标准库模块:有些模块直接被构建在解析器里,这些虽然不是一些语言内置的功能,可是他却能很高效的使用,甚至是系统级调用也没问题。这些组件会根据不一样的操做系统进行不一样形式的配置,好比 winreg (Windows注册表访问)这个模块就只会提供给 Windows 系统。应该注意到这有一个特别的模块 sys ,它内置在每个 Python 解析器中。可参考:http://www.javashuo.com/article/p-ncoptfrs-cm.html程序员
https://blog.csdn.net/sadfishsc/article/details/10390065app
Python第三方模块:非在解析器里的他人写的python脚本,可到官方提供的第三方模块网址查找、下载:https://pypi.org/。dom
应用程序自定义模块:本身写的python脚本。ide
模块做用:函数
1.可把程序分红一个个的文件,这样作程序的结构更清晰,方便管理。测试
2.文件里实现的功能可重复利用,提升开发效率。编码
在Python中用关键字import来引入某个模块,好比要导入模块time,就能够在文件最开始或使用以前的地方用 import 来引入。spa
语法:import 模块名
在调用模块中的函数时,必须加上模块名调用,由于可能存在多个模块中含有相同名称的函数,此时,若是只是经过函数名来调用,解释器没法知道到底要调用哪一个函数。为了不这样的状况,调用函数时,必须加上模块名。
import加载的模块分为四个通用类别:
1 使用python编写的.py文件
2 已被编译为共享库或DLL的C或C++扩展
3 包好一组模块的包,把一系列模块组织到一块儿的文件夹(注:文件夹下有一个__init__.py文件,该文件夹称之为包)
4 使用C编写并连接到python解释器的内置模块
import time time.sleep(1) #时间睡眠 # sleep() #会报错
咱们能够从sys.module中找到当前已经加载的模块,sys.module是一个字典,内部包含模块名与模块对象的映射,该字典决定了导入模块时是否须要从新导入。
一行导入多个模块
import time,random #模块之间用逗号隔开 print(time.time()) print(random.randint(1,3))
导入模块重命名:import ... as
有时候你导入的模块名称已经在你的程序中使用了, 或者你不想使用现有的名称。可使用一个新的名称替换原始的名称。
import time as tm print(tm.time())
python模块搜索路径
在任何一个python程序启动时,都会将模块的搜索路径收集到sys模块的path属性中(sys.path
)。当python须要搜索模块文件在何处时,首先搜索python解释器的内置模块(如time模块),若是不是内置模块,则搜索sys.path中的路径列表,搜索时会从该属性列出的路径中按照从前向后的顺序进行搜索,而且只要找到就当即中止搜索该模块文件。因此若是当前路径或 PythonPATH中存在与标准module一样的module,则会覆盖标准module。也就是说,若是当前目录下存在xml.py,那么在执行import xml时,导入的是当前目录下的module,而不是系统标准的xml.py。
import sys print(sys.path)
import语句是导入模块中的全部属性,而且访问时须要使用模块变量来引用,Python的from语句让你从模块中导入一个指定的部分到当前命名空间中。使用这种方式导入,不会整个模块导入到当前命名空间,它只会将import的内容导入。from.....import 也支持as模式,给导入的模块重命名。
from time import time,sleep start_time = time() print(start_time) sleep(2) stop_time = time() print(stop_time) print(stop_time-start_time)
导入一个模块的全部内容也可使用from…import*,但不推荐使用,由于可能形成变量命名冲突。
from time import * print(time()) #可直接使用time模块的全部功能,不需在前缀加模块名
命名冲突示例
from time import * #假如咱们不知道time模块里是否有time(),但在导入time模块的下方本身定义了一个名为time的函数 def time(): return '本身定义的time函数被调用' #在本身定义的time函数下方使用from time import * # from time import * print(time()) #函数名即变量名储存的是函数对象的引用,同名函数会存在引用覆盖。
注意:当Python程序导入其余模块时,要避免循环导入,,即A文件导入了B,B文件又导入了A.,否则总会出意向不到的问题….
使用模块能够避免函数名和变量名冲突。相同名字的函数和变量彻底能够分别存在不一样的模块中,所以,咱们本身在编写模块时,没必要考虑名字会与其余模块冲突。可是也要注意,尽可能不要与内置函数名字冲突。为了不模块名冲突,Python又引入了按目录来组织模块的方法,称为包(Package)。
包是一种管理 Python 模块命名空间的形式,采用"点模块名称"。好比一个模块的名称是 A.B, 那么他表示一个包 A中的子模块B
目录中只有包含一个叫作__init__.py的文件才会被认做是一个包,__init__.py
文件是必须存在的,不然,Python就把这个目录当成普通目录,而不是一个包。__init__.py
能够是空文件,也能够有Python代码。当包看成模块被导入时,__init__.py就会被执行加载。
在导入包的时候,Python会从sys.path中的目录来寻找这个包中包含的子目录。
Notes: 本身建立模块时要注意命名,不能和Python自带的模块名称冲突。例如,系统自带了sys模块,本身的模块就不可命名为sys.py,不然将没法导入系统自带的sys模块。
类的属性:
__doc__ 文档字符串
__name__ 类名称
__bases__ 父类组成的元组
__dict__ 保存类方法和变量等的字典
实例的属性:
__class__ 实例所属的类
__dict__ 保存实例数据的字典
模块的属性:
__dict__ 与模块相关的字典
__name__ 模块的名称
__file__ 模块文件的绝对路径
导入包:
导入包与导入模块的方式是同样的。当执行导入包时,__init__.py就会被执行加载。因此包其实也是个模块,__init__.py
能够是空文件,不过会影响from <包名> import * 和 import <包名> 这两种导入方式。
建立__init__.py文件:
目录中只有包含了叫作__init__.py的文件,才能被程序认做是包,模块才能被导入成功。如今咱们就在msg文件夹下建立一个__init__.py文件,而且在文件中写入__all__=[ 'module_name', 'module_name' ]。
能够在__init__.py中编写其余内容,在导入时,这些编写的内容就会被执行。
能够在__init__.py中向sys.path添加当前被调用模块路径。
__all__总结:
编写Python代码(不建议在__init__中写python模块,能够在包中在建立另外的模块来写,尽可能保证__init__.py简单)。
模块中不使用__all__属性,则导入模块内的全部公有属性,方法和类 。 模块中使用__all__属性,包中使用__all__属性,则表示只导入__all__中指定的属性,定义了当咱们使用 from <module> import * 导入某个模块/包的时候能导出的符号(这里表明变量,函数,类等) (固然下划线开头的变量,方法和类除外)。
须要注意的是 __all__ 只影响到了 from <package> import * 或 import <package> 这种导入方式, 对于 from <module|package> import <member> 导入方式并无影响,仍然能够从外部导入。
reload()简介:
不管时import仍是from,默认状况下,模块在第一次被导入以后,其余的导入都再也不有效。若是此时在另外一个窗口中改变并保存了模块的源代码文件,也没法更新该模块。这样设计缘由在于,导入是一个开销很大的操做(导入必须找到文件,将其编译成字节码,而且运行代码),以致于每一个文件、每一个程序运行不可以重复多于一次。当一个模块被导入到一个脚本,模块代码只会被执行一次。所以,若是你想从新执行模块里代码,能够用reload()函数,该函数会从新导入以前导入过的模块。reload()是imp模块中的一个函数,因此要使用imp.reload()以前,必须先导入imp,它的参数是一个已经成功被导入过的模块变量。也就是说该模块必须在内存中已经有本身的模块对象。reload()会从新执行模块文件,并将执行获得的属性彻底覆盖到原有的模块对象中。也就是说,reload()会从新执行模块文件,但不会在内存中创建新的模块对象,因此原有模块对象中的属性可能会被修改。语法:reload(module_name)。
import random def mul(x,y): return x*y print(random.randint(3,3)) #此时random.randint()是随机函数。 random.randint = mul #变为乘法函数 print(random.randint(3,3)) from imp import reload reload(random) print(random.randint(3,3)) #变回随机函数。
py文件分两种:用于执行的程序文件和用于导入的模块文件。当直接使用python a.py
的时候表示a.py是用于执行的程序文件,经过import/from方式导入的py文件是模块文件。
__name__
属性用来区分py文件是程序文件仍是模块文件:
__main__
对于python来讲,由于隐式自动设置,该属性就有了特殊妙用:直接在模块文件中经过if __name__ == "__main__"
来判断,而后写属于执行程序的代码,若是直接用python执行这个文件,说明这个文件是程序文件,因而会执行属于if代码块的代码,若是是被导入,则是模块文件,if代码块中的代码不会被执行。
导入模块的过程:
python的import是在程序运行期间执行的,并不是像其它不少语言同样是在编译期间执行。也就是说,import能够出如今任何地方,只有执行到这个import行时,才会执行导入操做。且在import某个模块以前,没法访问这个模块的属性。
python在import导入模块时,首先搜索模块的路径,而后编译并执行这个模块文件。虽然归纳起来只有两个过程,但实际上很复杂。
Python中全部加载到内存的模块都放在sys.modules。sys.modules是一个全局字典,该字典是python启动后就加载在内存中。每当程序员import一个模块文件时,首先会在这个字典查找是否已经加载了此模块,若是加载了则只是将模块的名字加入到正在调用import的模块的Local名字空间中(若是在全局做用域导入模块,则把模块名加入全局命名称空间,若是是在局部做用域导入模块,则模块名加入局部名称空间)。若是没有加载则从sys.path目录中按照模块名称查找模块文件,模块文件能够是py、pyc、pyd,找到后建立新的module对象(此时module对象的 __dict__ 属性为空),并将模块名与module对象的引用加入字典sys.modules中,而后编译、执行模块文件载入内存,并填充module对象的属性__dict__,按照必定的规则将一些结果放进这个module对象中,最后将模块名称导入到当前的Local名字空间。
注意细节:编译、执行模块文件、将结果保存到module对象中。
关于编译、执行模块文件的细说:
模块第一次被导入的时候,会进行编译,并生成.pyc字节码文件,而后在python工做目录的环境下执行这个pyc文件,而非模块所在的目录环境。当模块被再次导入时,若是检查到pyc文件的存在,且和源代码文件的上一次修改时间戳mtime彻底对应(也就是说,编译后模块文件的源代码没有进行过修改),则直接装载这个pyc文件并执行,不会再进行额外的编译过程。固然,若是修改过模块文件的源代码,将会从新编译获得新的pyc文件。
注意,并不是全部的py文件都会生成编译获得的pyc文件,对于那些只执行一次的程序文件,会将内存中的编译结果在执行完成后直接丢弃(多数时候如此,但仍有例外,好比使用compileall模块能够强制编译成pyc文件),但模块会将内存中的编译结果持久化到pyc文件中。另外,运行字节码pyc文件并不会比直接运行py文件更快,执行它也同样是一行行地解释、执行,惟一快的地方在于导入装载的时候无需从新编译而已。
执行模块文件(已完成编译)的时候,按照通常的执行流程执行:一行一行地、以代码块为单元执行。通常地,模块文件中只用来声明变量、函数等属性,以便提供给导入它的模块使用,而不该该有其余任何操做性的行为,好比print()操做不该该出如今模块文件中,但这并不是强制。
总之,执行完模块文件后,这个模块文件将有一个本身的全局名称空间,在此模块文件中定义的变量、函数等属性,都会记录在此名称空间中。
最后,模块的这些属性都会保存到模块对象中。因为这个模块对象赋值给了模块变量module_name,因此经过变量module_name能够访问到这个对象中的属性(好比变量、函数等),也就是模块文件内定义的全局属性。
参考连接:https://www.cnblogs.com/qq78292959/archive/2013/05/17/3083961.html
https://www.jianshu.com/p/178c26789011
目录结构package目录与test目录是同级的:
print('package/package2目录下的__init__模块被加载')
print('package/package2目录下的module1.py执行加载') print('package/package2目录下module1模块的__name__属性值为:{}'.format(__name__))
'''导入与父目录的父目录同级的模块''' # import test.module1 as md from test import module1
__all__ = ['module1'] print('package目录下的__init__模块被加载')
print('package目录下的module1.py执行加载') print('package目录下的module1模块的__name__属性值为:{}'.format(__name__)) def add(x,y): return x+y def mul(x,y): return x*y
'''同目录下的模块导入方式''' # import module1 # from package import module1 # from module2 import * #不推荐使用,避免命名冲突 # print('package目录下的module1.py执行加载') # print('module1模块的__name__属性值为:{}'.format(__name__)) # def add(x,y,z): # return x+y+z # def mul(x,y,z): # return x*y*z # print(module1.add(2,3)) '''导入与父目录同级的模块的方法''' # import test #导入test包,实质上是导入test目录下的 __init__模块,此模块有什么属性,导入的test就有什么属性。 # print(test.module1.__name__) # import test.module1 as md # from test import module1 '''导入同目录下的包''' # import package2.module1 as md # from package2 import module1
print('test目录下的__init__.py被加载') __all__ = ['module1'] # 若容许经过包名导入全部模块,必须给__all__实现赋值 from test import * #表示导入同目录的全部模块
print('test目录下的module1被加载')
若python解释器没法找到可根据模块的所在目录给sys.path添加搜索路径:
或是:
import sys,os BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(BASE_DIR) from bao1 import a1 a1.aa1(99)
编写一个hello.py
的模块
1 #!/usr/bin/env python3 2 # -*- coding: utf-8 -*- 3 4 ' a test module ' 5 6 __author__ = 'Michael Liao' 7 8 import sys 9 10 def test(): 11 args = sys.argv # argv参数用列表存储命令行的全部参数 12 if len(args)==1: # 当列表长度为1时即只有一个参数时 13 print('Hello, world!') 14 elif len(args)==2: # 当命令行有两个参数时 15 print('Hello, %s!' % args[1]) 16 else: 17 print('Too many arguments!') 18 19 if __name__=='__main__': 20 test()
第1行和第2行是标准注释,第1行注释可让这个hello.py文件直接在Unix/Linux/Mac上运行,第2行注释表示.py文件自己使用标准UTF-8编码;
第4行是一个字符串,表示模块的文档注释,任何模块代码的第一个字符串都被视为模块的文档注释;
第6行使用__author__
变量把做者写进去,这样当你公开源代码后别人就能够瞻仰你的大名;
第8行是导入sys模块,导入sys
模块后,咱们就有了变量sys
指向该模块,利用sys这个变量,就能够访问sys模块的全部功能。sys
模块有一个argv
变量,用list
存储了命令行的全部参数。argv
至少有一个元素,由于第一个参数永远是该.py文件的名称,例如:运行python3 hello.py
得到的sys.argv
就是['hello.py']
,注意这里python3
不算是参数;运行python3 hello.py Michael
得到的sys.argv
就是['hello.py', 'Michael]
。
第19行表示当咱们在命令行运行hello
模块文件时,Python解释器把一个特殊变量__name__
置为__main__
,而若是在其余地方导入该hello
模块时,if
判断将失败,所以,这种if
测试可让一个模块经过命令行运行时执行一些额外的代码,最多见的就是运行测试。
以上就是Python模块的标准文件模板,固然也能够所有删掉不写,可是,按标准办事确定没错。