目录
模块和包
模块(module)
包(package)
导包和模块调用
模块调用
模块调试
导包
库
python标准库
第三方库
解释器调用模块的原理
内置模块
模块搜索机制:sys.path
添加sys.path的方法
Python中每一个.py文件就是一个模块(module),功能的实现是通过不同模块之间的调用完成的。划分模块的意义在于方便我们调用和修改,模块的划分一般根据不同的功能来命名和存放。
项目开发中,按照代码文件功能的不同,将相同功能的模块放到同一个目录文件中,这样可以方便管理和使用,这些用来存储文件的目录就是包(package)。在项目包中,每个包文件下都需要一个名为__init__.py的初始化文件,python解释器通过这个初始化文件来识别python包,从python3.2以后不需要再写,通常情况下创建这个文件肯定不会出错。初始化文件里面不需要加入代码,是一个空文件,有时候根据需要也可以加入代码,加上代码后当这个包里面的模块被导入的时候,__init__.py中的代码也会被执行。
在导包的时,想要一次导入这个包中所有的模块,需要在初始化文件中添加__all__方法,[] 中为模块名,没有这个方法不能使用 * 导入。使用 * 后,会导入__all__方法中添加的所有模块。
# __init__.py
__all__ = ['b1','b2','b3']
导入后的模块都是作为当前模块中的局部变量被使用,在使用的时候不用担心操作后对源模块中的对象产生改变。
假设现在有三个不同的模块,a , b , c (这三个模块是存放在同一个目录文件下的平行文件:详细原因参考sys.path)
现在在实现a模块的代码功能时需要用到c中的对象,调用的方法如下:
方法一:import 模块名
import c
这样c 就成了模块a里面的一个变量,这个变量指向的是一个模块对象 (一切皆对象,模块诚然)
在c模块中有多个对象方法,如其中有函数c_1 , c_2 , c_3 , ... ,而我们需要使用的是c_2,这时代码写法为:模块名.方法名 如下:
import c
c.c_2()
方法二:from 模块名 import 函数对象名
如果我们只需要使用c中的函数对象 c_2 , c_3,导入方法如下:
from c import c_2
from c import c_3
也可以一起导入,之间使用逗号隔开,如下:
from c import c_2,c_3
可以使用 * 导入,from c import *,使用 * 时表示导入对应模块中的所有对象。如果导入的不同模块中有重名的对象,而这两个对象在当前文件中都要用到,就需要给导入的对象重命名,如果不重新命名,后面导入的对象会覆盖前面导入的。如b和c中都有要使用的对象lists_a,写法如下:
from b import lists_a
from c import lists_a as lists_a2
在调用c中的lists_a对象时,调用lists_a2即可。
as用来重新赋值,在导入模块的时候,除了有同名的导入对象的时使用,在导入的对象名太长,使用不方便时,也可以使用as赋值。
每个模块都有一个__name__属性,当其值是'__main__'时,表明该模块自身在运行,否则是被引入。
# b2.py
if __name__ == '__main__':
def debug():
print('当前模块调试使用')
debug()
If __name__ == ‘__main__’:中的代码只能作为当前模块文件调试使用,其他模块引入后不能使用。当文件是被调用时,__name__的值为模块名,当文件被执行时,__name__为'__main__'。
# test.py
from pyt import b2
b2.debug()
被其他文件调用时,使用__name__方法返回模块名:
# test.py
from pyt import b2
print(b2.__name__)
方法与模块的调用一样
方法一:import ... 方法,import后面跟的包对象为存放所使用对象的最外层的包目录。
在导入这个对象时就要从引用对象的顶级目录开始。整体作为一个被引用的对象,其中的函数等对象作为它的方法被使用,所以每次需要写全这个对象,使用起来比较麻烦,可以是使用第二种方法。
方法二:from ... import ... 方法,from后导入包的方法与方法一相同,import后面指明需要导入的变量或函数对象,作为当前模块的使用对象。
模块文件中提供了被其他模块调用的功能函数或者类等功能,这些被调用的模块文件就称为库。
标准库里面的一部分被称之为内置库,这些库中的类型和方法不需要import导入,可以直接使用,内置库函数官网:https://docs.python.org/3/library/functions.html
还有一些库需要import导入才能使用,常见的有sys,os,time,json等。
Python安装第三方库时,使用pip命令
pip安装时,访问国外PYPI可能较慢,可以使用国内镜像网站,在命令行最后加参数:-i https://pypi.douban.com/simple/
安装时如果出现SSL错误,改用http协议下载,在后面添加参数:--trusted-host pypi.douban.com
解释器在导入时会首先解释器内置模块中寻找是否有导入的模块文件 。内置模块是内置python解释器程序中的模块,模块有用C语言编译链接存放在解释器中。属于解释器的一部分,在解释器运行时,这些模块就在解释器中,不需要查找,如:time, sys, math等。查看解释器中包含的模块方法:
import sys
print(sys.builtin_module_names)
查看结果:
('_abc', '_ast', '_bisect', '_blake2', '_codecs', '_codecs_cn', '_codecs_hk', '_codecs_iso2022', '_codecs_jp', '_codecs_kr', '_codecs_tw', '_collections', '_contextvars', '_csv', '_datetime', '_functools', '_heapq', '_imp', '_io', '_json', '_locale', '_lsprof', '_md5', '_multibytecodec', '_opcode', '_operator', '_pickle', '_random', '_sha1', '_sha256', '_sha3', '_sha512', '_signal', '_sre', '_stat', '_statistics', '_string', '_struct', '_symtable', '_thread', '_tracemalloc', '_warnings', '_weakref', '_winapi', '_xxsubinterpreters', 'array', 'atexit', 'audioop', 'binascii', 'builtins', 'cmath', 'errno', 'faulthandler', 'gc', 'itertools', 'marshal', 'math', 'mmap', 'msvcrt', 'nt', 'parser', 'sys', 'time', 'winreg', 'xxsubtype', 'zlib')
Python在执行模块调用时使用sys.path方法查找。import导入一个模块时,解释器就会依次到sys.path包含的目下寻找同名的模块,如果有,会立即被使用,后面的路径将不会去查找,即便是有多个同名的模块,也只会使用第一个查到的路径中的模块。当启动一个脚本文件时,这个脚本文件的路径和脚本文件的目录路径都会自动被添加到sys.path中作为模块搜索路径使用。可以通过运行sys.path语句来查看有哪些路径。这些路径存放在列表中。
import sys
print(sys.path)
结果如下:
['E:\\pycharm\\mypython', 'E:\\pycharm\\mypython', 'E:\\python\\python38.zip', 'E:\\python\\DLLs', 'E:\\python\\lib', 'E:\\python', 'E:\\python\\lib\\site-packages']
出现两个相同的路径,一个是当前脚本文件的目录路径,一个当前脚本路径。
对于我们自己创建的模块在导包时sys.path查找不到,这时需要添加路径到sys.path下,方法有下面几种: