python模块和包
1.深入理解python库
库Library:一种对特定功能集合的通俗说法
包含一些程序功能,通过import引入使用,对应模块和包。
标准库:Standard Library,与python解释器一同安装的库。
第三方库:Third-Party Library,需要额外安装的库。
模块Module:以单个文件为命名空间的代码片段
模块是一个单独的.py文件,模块名就是文件名。
模块本质是一个独立的、由模块名组织的命名空间。
模块中可以引入其他模块,并由一些python语法来约束和管理。
包Package:由一组模块构成、有层次命名空间的程序功能
包由多个模块(多个.py文件)有组织的构成。
模块的组织方式构成了命名空间的层次结构。
包是模块的上一级组织概念,其中可以包括子包。
模块是一切库的基础单元
包由模块构成,可以理解为:包是目录,模块是.py文件。
库是通俗说法,具体指python的模块和包。
python库的核心是模块及模块的组织方式(体现为命名空间)。
模块是一个命名空间
模块对应单独的.py文件,它是一个独立的命名空间。
模块内可能包含:类、函数、语句(直接可执行)、变量等元素。
模块内还包括一些其他对模块进行约束和管理的语法元素。
module_var=1
class module_class:
mc_classattr=1
def __init__(self,mc_instattr=1):
self.mc_instattr=mc_instattr
def mc_fun(self):
return "Method with a count of {}".format(self.mc_classattr)
def module_func():
print("Module Function")
print("Module Statement")
#命名为m.py
模块的调用
import m
print(m.module_var)
mc=m.module_class(99)
print(mc.mc_func())
m.module_func()
#.
#访问模块内顶层命名空间的变量,类和函数。
'''
输出为:
Module Statement #当使用import调用m模块,m模块中的所有语句会被执行一遍
1
Method with a count of 1
Module Function
'''
from m import *
print(m.module_var)
mc=m.module_class(99)
print(mc.mc_func())
m.module_func()
输出为:
'''
Module Statement
1
Method with a count of 1
Module Function
'''
我们在名字前增加一个下划线
_module_var=1 #加一个下划线
class module_class:
mc_classattr=1
def __init__(self,mc_instattr=1):
self.mc_instattr=mc_instattr
def mc_fun(self):
return "Method with a count of {}".format(self.mc_classattr)
def _module_func():
print("Module Function")
print("Module Statement")
#命名为m.py
'''
此时我们用import m的方式依然可以调用
但是当我们用from m import *程序运行会报错
'''
模块是一个命名空间
模块中语句:在import时一次性执行。
模块内的变量、类和函数:在import时采用方式可访问。
单下划线的顶层命名元素:不会在from … import * 时被导入。
包是一个有层次的命名空间
每个包需要包含一个__init__.py文件表达包的组织。
_ _ init _ _.py可以是空文件,即,文件存在即可。
每个包可以嵌套包含更多子包。
通过包的组织可以形成由英文句号(.)分隔的层次化命名空间。
_ _ init _ _.py用来构成包的定义,区分于包含.py文件的普通目录。
包、子包和模块可以用import 进行导入或单独导入。
模块的名称属性
名称属性:表达模块名称的预定义变量
属性
描述
_ _name _ _
模块或包的名字,例:m. _ _ name _ _
def _module_func():
print("Module Function")
module_var=1
print("Module Statement")
print(__name__)
'''
Module Statement
__main__
'''
import m
'''
输出为:
Module Statement
m
'''
当程序以脚本方式直接执行时,_ name _的值为‘ _ _ main _ _’。
当程序以模块方式被引用时,_ name _ 的值为模块名称。
作用:区分程序以何种方式执行。
def _module_func():
print("Module Function")
if __name__=="__main__":
module_var=1
print("Module Statement")
print(__name__)
'''
Module Statement
__main__
'''
import m
'''
无输出
'''
if _ _ name _ _ == ’ _ _ main _ _ ’ :
当程序以脚本方式执行时,后续代码可以执行,否则不执行。
作用1:作为模块主体功能的单元测试部分。
作用2:作为模块内部保留的额外功能部分。
模块和包的构建
模块的构建
功能闭包:单一.py文件实现单一且完整的功能。
抽象适度:用函数或类进行抽象,结合功能选择合适抽象。
操作闭包:模块无顶层可执行语句,导入时无输出。
模块的构建原则
功能闭包:功能定义要清晰、设计要合理(紧耦合vs松耦合)。
抽象适度:采用类或函数,尽量选择一种;多种也无妨。
操作闭包:采用 _ _ name _ _ ,无全局可执行语句,尽量无全局变量。
"这是模块描述" #第一行增加描述
class module_class:
mc_classattr=1
def __init__(self,mc_instattr=1):
self.mc_instattr=mc_instattr
def mc_func(self):
return "Method with a count of {}".format(self.mc_classattr)
if __name__='__main__':
import sys
mc=module_class(sys.argv[1])
print("Module Statement") #顶层功能的引用放在__name__后
#dir()函数:以列表形式返回模块所使用的命名。
import m
print(dir(m))
包的构建
常规包:Regular Packages,通过 _ _ init _ _.py对文件和目录组织形成的包。
命名空间包:Namespace Packages,由更分散子包组成的包。
子包的位置可以再文件系统中不连续。
子包可以是压缩文件或网络连接或其他系统资源。
常规包
连续目录空间表达的、有层次的命名空间。
每个目录中包含一个 _ _ init _ _ .py,可以是空文件。
当包/子包被导入时,对应目录的 _ _ init _ _.py文件将被执行。
每个包仅被导入一次,且包导入按照层次结构进行。
直接导入包不行,需要进行到模块层次。(import pkg.pkg1包)
from … import …直接导入具体模块,可以简化调用时命名空间表达。
(但是from … import * 需要额外代码的编写。)
_ _ all _ _ 属性
from…import * 形式需要在 _ _ init _ _.py文件中增加 _ _ all _ _属性赋值。
_ _all _ _ 需要被赋值为列表对象,包含当前包下所有希望被导入的模块名称。
_ _ all _ _ 用来辅助导入模块,但不能辅助导入列表。
__all__=['m1','m2']
#在__init__.py中写入,再使用from ... import *就可以了。
命名空间包
命名空间包:表达命名空间层次结构的一种逻辑包形式
命名空间中各部分可以在不同的文件系统位置。
命名空间中各个子包并不包含__init__.py文件(普通目录!)
python解释器通过sys.path变量来隐式维护命名空间包。
import sys
sys.path+=['project1','project2']
import pkg1.m1
import pkg1.m3
pkg1.m1.mecho(123)
pkg1.m3.mecho('python')
print(pkg1.__path__)
sys.path:指定搜索路径的字符串列表
指定import时搜索模块或包的路径列表,路径是相对或绝对路径。
sys.path是一个列表类型,可以sys.path.append(p)增加新路径p。
载入后,根据其中包的名称和层次结构自然组成了命名空间包。
_ _ path _ _ 属性
记录了某个包(命名空间)的绝对或相对路径,列表类型。
常规包:路径是单一的,列表中只有一个元素。
命名空间包:路径是多元的,列表中可能有多个元素。
import系统:扩展命名空间及功能的方法
构成:import保留字、_ import _()函数和importlib标准库
步骤:模块的查找、模块的加载
价值:import系统是python代码复用和命名空间管理的精髓。
import保留字:调用 _ import _进行模块查找,以及模块的加载。
_ import _ ()函数:模块的查找,建立模块对象。
importlib标准库:与import系统相关的丰富API。
模块的加载
模块的查找
模块对象
ImportError
当前命名空间
万物皆对象:模块被导入后成为了对象
模块的对象形式:模块在程序中使用都是以对象形式体现的。
类似类对象,模块对象只有一个。
模块对象生成时,模块中代码会被执行,因此会有类对象产生。
模块的查找
查找路径:1.sys.modules
第一步查找sys.modules,之前被引入模块的缓存(cache)。
sys.modules是一个字典,:。
如果模块不再sys.modules中,则进入下一步。
查找路径:2.查找策略
用户通过import钩子扩展的查找模式。
内置模块的路径。
sys.path(列表变量)提供的加载路径,可以是zip文件或URL。
import钩子:import hook
扩展查找模块的方式:meta_path方式和import路径方式。
meta_path:将查找方法增加到sys.meta_path列表变量。
import路径:将查找方法注册到sys.path_hooks列表变量。
建立模块对象的过程
找到模块后,如果模块对象存在,则使用现有模块对象。
创建一个新的模块对象,将其加入sys.modules。
在程序当前命名空间执行模块代码。
创建对象:importlib.abc.loader.create_module()
执行对象:importlib.abc.loader.exec_module()
模块对象的命名空间
模块的命名空间与引用位置有直接关系。
如果引用在文件顶层,则使用文件顶层命名空间访问模块。
如果引用在非顶层,则使用局部命名空间访问模块。
import的三种使用方式
import
from import
import as
import
当前命名空间下的一个子命名空间。
成功加载后,产生一个与同名的。
实际上:.方式访问。
from import
将导入元素加载到当前命名空间下。
成功加载后,产生类对象或函数对象,覆盖同名对象。
实际上:或方式访问。
import as
当前命名空间下的一个子命名空间。
成功加载后,产生一个与同名的。
实际上:.方式访问。
python第三方库的发布
发布前的准备
PyPI:python package index,用来登记第三方库信息。
Github、bitbucket:存储第三方库源代码及文档。
目标:通过pip进行安装和管理、源代码和文档网络可管理。
一些基本概念
项目project:pypi上一组发布和文件的统称。
发布release:项目的一个特定版本,每个发布有一个确定的版本号。
文件file:即package,一次发布包含的具体文件。
setuptools
twine
.py源代码
一种分发形式
pypi:pypi.org
更新setuptools、wheel、twine工具。
注册pypi账户。
第一步:整理目录结构。
第二部:创建其他文件(setup.py:配置发布信息的文件,很重要。README.md:markdown格式的说明文件。LICENSE:版权声明文件。)
第三部:执行打包命令(python setup.py sdist bdist_wheel)
第四部:执行发布命令(twine upload dist/*)
打包发布:对文件整理打包后进行发布。
源发布:发布源代码的方式。
可执行发布:发布编译后可执行代码的方式。