一、模块
在python中,模块就是一个代码文件,模块中可以定义类、函数、变量,也可以包含可执行的代码。
使用Import导入。
1.1 搜索路径
搜索模块时,python会按照sys.path列表中的路径,依次进行搜索。可以通过sys.path查看搜索路径。
将模块的路径添加到sys.path路径的三种方法:
(1)动态添加
sys.path.append(模块路径),动态添加需要每次在程序启动时,向sys.path添加。
(2)若经常用到,可以在Python安装目录下的Lib\site-packages文件夹下建立一个纯文本文件,扩展名为.path。
(3)修改环境变量。
1.2 导入模块
可以一次导入多个模块
1.3 导入指定的模块属性
如:from xlutils.copy import copy
1.4 加载模块
在程序开发中,一个模块可以在多处被import,但Python只会导入一次,因为所有加载到内存的模块都会被放入到sys.modules中。
加载模块会导致这个模块被“执行”。
1.5 名称空间
Python程序执行时存在内建名称空间、全局名称空间和局部名称空间。
1.6 “编译”的Python文件
Python中一旦被引用的模块(假设为example.py)被成功编译,其对应的编译版本example.pyc就会被创建。如果创建成功,那么example.py的修改时间会记录在example.pyc中,下次载入时,如果两个文件的修改时间不匹配,则.pyc文件就会被忽略。如果有可用的.pyc文件,则会使用.pyc文件提高模块的加载速度。当程序需要加载多个模块时,.pyc文件能够有效地提高程序的启动速度。
1.7 自动导入模块
sys模块的modules变量中存储了完整且成功导入的模块信息。
1.8 循环导入
循环导入(circular import)是一种死循环,即A代码需要B才能执行,而偏偏B代码是建立在A代码基础上。
二、包
包(Package)可以看成模块的集合,只要一个文件夹下面有__init__.py文件,那么该文件夹就可以看作一个包。包下面还可以有子包。
导入包的过程与导入模块的基本一致,只是导入包的时候会执行目录下的__init__.py,而不是模块里的语句。另外,如果只是单纯地导入包,而包的__init__.py中又没有明确的其他初始化操作,那么此包下面的模块是不会自动导入的。
例如,一个简章的包目录
Pac/
__init__.py
Subpac1/
__init__.py
Modu1.py
Subpac2/
__init__.py
Modu1.py
导入方法:
from Pac.Subpac1 import Modu1
import Pac.Subpac1.Modu1
三、程序打包
Python提供了Distutils、Setuptools、Py2exe、PyInstaller、cx_freeze等程序打包工具,其中,Setuptools是Distutils的增强工具,Py2exe、PyInstaller、cx_freeze是windows平台下制作exe文件的工具。Distutils包含在Python的标准版发行包中。
3.1 Distutils
例如,首先建立一个hello.py文件。
(1)建立一个setup.py文件,内容如下:
f
rom distutils.core import setup
setup(name='hello',version='1.0',description='hello ccc',author='cheng',py_modules=['hello'])
(2)执行打包命令:
>>>python setup.py sdist
结果:该命令创建了dist目录,并将要打包的文件复制到hello-1.0.zip的压缩文件中。
3.2 py2ext
py2exe暂时到目前只支持到3.4版本(包括cxfreeze),在3.5版本中会报错。
(1)建立建立一个setup.py文件,内容如下:
from distutils.core import setup
import py2exe
setup(console=[‘hello.py’])
(2)执行命令:
>>>python setup.py py2exe
以下内容转载自:
https://blog.csdn.net/qq_33961117/article/details/81561221
‘’’
模块:包括了一系列功能的集合体
三种来源:1.内置的模块 2. 第三方的模块 3. 自定义模块
四种格式:
- 用python编写的.py文件
2.已被编译为共享库或DLL的C或者C++扩展 - 一系列模块组织到一起的文件夹(主:文件夹下有一个__init__.py文件,该文件夹称之为包)
- 使用C编写并链接到python解释器的内置模块
为何要使用模块?
1、使用自定义模块的好处:从文件级别组织程序,更方便管理,减少代码冗余
2、使用内置或第三方模块的好处:拿来主义,提升开发效率
ps:
如果你退出python解释器然后重新进入,那么你之前定义的函数或者变量都将丢失,
因此我们通常将程序写到文件中以便永久保存下来,需要时就通过python test.py方式去执行,
此时test.py被称为脚本script。
‘’’
‘’’
使用模块(import的使用):
1. import 模块名 导入模块
总结:1.1在使用的时候必须以:模块名.名字的形式
1.2 优点:指名道姓的像某一个名称空间要名字,不会与当前名称空间的名字冲突
1.3 缺点:但凡调用都需要加上前缀,使用不够简洁
注:首次导入模块时:
1.产生一个模块的名称空间
2.执行模块文件,在执行过程中,将产生的名字变量传入名称空间的内存地址中
3.在执行文件中的到一个模块名,其指向模块文件的名称空间地址
之后的重复导入操作,都只是指向之前导入的结果地址,不会重新执行首次导入的三步操作4
2.在文件中访问模块名称空间中名字的语法:模块名.名字
例:time.x --------》寻找time模块文件中的x名字(或许是变量名,或许是函数名)
3.一行多个模块同时导入(不推荐)
例:import time,os.spam
4.可以为模块起别名(注:模块名应该全为小写)
例:import time as t
‘’’
‘’’
使用模块(from…import…):
1.优点,使用时不需要加前缀,使用简洁
2.缺点,易重名产生冲突,且后定义赋值 覆盖 前一个定义赋值的值
3.取模块内全部名字(不推荐) from time import *
*对于模块内__all__列表存储名字,若没有另外定义则返回所有名字(不包含_开头的变量名)
4.起别名:from time import m as m1
注:首次导入模块时:
1.产生一个模块的名称空间
2.执行模块文件,在执行过程中,将产生的名字变量传入名称空间的内存地址中
3.在执行文件中直接拿到指定模块内的名字(或变量或函数)
例: from time import x 取出了time模块的x名字
‘’’
‘’’
循环导入问题(test文件:m1,m2,run):
模块的导入会在执行文件的时候创造名称空间,且仅一次
如果执行步骤上python发现一家存在已创建的名称空间,则不会继续导入
若执行文件在导入名字的时候被模块1内的导入模块2打断,则不会导入模块1的后续变量
因为,python当检测到已经存在名称空间,则不会继续往名称空间内添加。
解决方法一:
把循环导入的语句放到名字的下方
原因:让执行文件导入模块1的时候,直接导入所有模块内名字,不会被模块1内的模块2导入打断
解决方法二:
将循环导入语句放到函数内
原因:不执行函数的时候,只检测函数语法而不运行函数
‘’’
‘’’
区别.py文件是执行文件还是模块文件(name):
即:判断文件的__name__属性
当文件被执行时(执行文件),name == ‘main’
当文件被导入时(模块文件),name == ‘模块名’
注:(快捷方式) 输入main 自动提示 if name == ‘main’
‘’’
‘’’
模块的搜索路径:
模块搜索路径的优先级:
1.内存中,已经加载过的
2.内置模块
3.sys模块中的path列表(sys.path),以当前执行文件所在文件夹绝对路径为首
强调:sys.path(环境变量)中的路径以执行文件的路径为准,包括被导入模块的环境变量
(测试练习 环境变量测试文件夹内)
注:若找不到路径,解决方法:
1.在执行文件中的sys.path内添加模块文件所在路径(处理环境变量),可以sys.path.append(绝对路径)
2.(子文件夹)from 和执行文件同级的文件夹名 import 模块文件名
3.(二级及以上子文件夹)from dir1.dir2 import m2 ---->dir1是dir2的父文件夹,m2位于dir2文件夹中
‘’’
‘’’
绝对导入和相对导入:
绝对导入:以执行文件的sys.path为依据导入
优点:执行文件和模块文件都可以使用
缺点:所有导入都以sys.path为依据,导入麻烦
相对导入:参照当前文件的文件夹为起始查找文件,称为相对导入
符号:.代表当前所在文件,..代表上级文件夹,...代表上上级文件夹
例:from . import m2 ; from .dir1 import m2
优点:导入更加简单
缺点:只能在被导入的模块中使用,不能在执行文件中使用
‘’’
‘’’
软件开发的目录规范:
-ATM
-bin
-start.py
#启动文件,即 main文件
import sys,os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
#BASE_DIR 讲ATM项目文件夹路径加入环境变量
sys.path.append(BASE_DIR)
from core import db
#导入核心逻辑模块 用于后续综合功能
if __name__ = 'main' :
db.run()
#用于 执行判断
-conf
-setting.py
#设置文件,用来保存全局使用的变量名
import os
BASE_DIR = os.path.DIRNAME(os.path.DIRNAME(__file__))
DB_PATH=os.path.join(BASE_DIR,'db','db.json')
LOG_PATH=os.path.join(BASE_DIR,'log','access.log')
LOGIN_TIMEOUT=5
.......
-core
-db.py
#核心逻辑代码,不包括核心逻辑中存在的需求代码
from conf import settings
from lib import common
import time
def login():
#登陆
print('login')
def register():
#注册
print('register')
...
-db
-db.json
#数据库文件,用来保存用户登陆信息
-lib
-common.py
#自定义模块,可用来辅助完成核心逻辑所需模块
from conf import settings
import logging
import logging.config
import json
def get_logger(name):
logging.config.dictConfig(settings.LOGGING_DIC) # 导入上面定义的logging配置
logger = logging.getLogger(name) # 生成一个log实例
return logger
def conn_db():
db_path=settings.DB_PATH
dic=json.load(open(db_path,'r',encoding='utf-8'))
return dic
-log
-access.log
#按照setting文件中的格式,保存操作日志
-readme.txt
#项目解释文件
‘’’
‘’’
包:包就是一个包含有__init__.py文件的文件夹,本质是一种模块
创建包的目的:
为了用文件夹将文件/模块组织起来
导入包的三部曲:
1.以包下的__init__.py文件为基准来产生一个名称空间
2.执行包下的__init__.py文件的代码,将执行过程中产生的名字都丢入名称空间
3.在当前执行文件中拿到一个p1,p1指向__init__.py名称空间
导入包需要注意的问题:
1.但凡是在 导入语句 中带点的,点的左边都必须是一个包
2.包内部模块的绝对导入的起始位置都是以包的顶级目录为起始点
3.包内部模块的导入通常应该使用 相对导入 ,方便设计者对包顶级目录的修改操作
.-本级 …-上级 …-上上级
注意:
1.相对导入 只能在包内部的模块之间互相导入
2. …上一级 不能超出顶级包
注意:
1. 在python3中,即使包下没有__init__.py文件,import 包仍然不会报错
而在python2中,包下一定要有该文件,否则import 包报错
2. 创建包的目的不是为了运行,而是被导入使用
记住,包只是模块的一种形式而已,包的本质就是一种模块
‘’’