模块
1 什么是模块
模块就是一系列功能的集合体
模块有三种来源
1. 内置的模块
2. 第三方的模块
3. 自定义模块
模块的格式:
1 使用python编写的.py文件
2 已被编译为共享库或DLL的C或C++扩展
3 把一系列模块组织到一起的文件夹(注:文件夹下有一个__init__.py文件,该文件夹称之为包)
4 使用C编写并链接到python解释器的内置模块
2 为何要用模块
1. 使用内置的或者第三方模块的好处是: 拿来主义,可以极大提升开发效率
2. 使用自定义模块的好处是: 可以减少代码冗余(抽取我们自己程序中要公用的一些功能定义成模块,然后程序的各部分组件都去模块中调用共享的功能)
3 如何用模块
大前提: 一定要区分开谁是执行文件,谁是被导入模块
import导入模块
# spam.py
print('from the spam.py')
money=1000
def read1():
print('spam模块:',money)
def read2():
print('spam模块')
read1()
def change():
global money
money=0
# 文件名是spam.py,模块名则是spam
# 首次导入模块发生3件事
# 1. 会产生一个模块的名称空间
# 2. 执行文件spam.py,将执行过程中产生的名字都放到模块的名称空间中
# 3. 在当前执行文件的名称空间中拿到一个模块名,该名字指向模块的名称空间
import spam
# 之后的导入,都是直接引用第一次导入的成果,不会重新执行文件
import spam
import spam
import spam
import spam
# 在执行文件中访问模块名称空间中名字的语法:模块名.名字
import spam
print(spam.x) # 指名道姓地跟spam要名字x,肯定不会与当前执行文件中的名字冲突
x # 向当前执行文件的名称空间要名字
money=11111111111111111111111
print(spam.money)
print(spam.read1)
print(spam.read2)
print(spam.change)
spam.read1()
def read1():
print('run.py --> read1')
spam.read2()
spam.change()
print(spam.money)
print(money)
# 总结import导入模块:在使用时必须加上前缀:模块名.
# 优点: 指名道姓地向某一个名称空间要名字,肯定不会与当前名称空间中的名字冲突
# 缺点: 但凡应用模块中的名字都需要加前缀,不够简洁
# 一行导入多个模块(不推荐)
import spam,os,time
# 可以为模块起别名(注意:模块名应该全为小写)
import spam as sm
print(sm.money)
print(sm.read1)
from...import...导入模块
# spam.py
print('from the spam.py')
__all__ = ['money','read1'] #from spam import *
money=1000
def read1():
print('spam模块:',money)
def read2():
print('spam模块')
read1()
def change():
global money
money=0
money=200
# 首次导入模块发生3件事
# 1. 创建一个模块的名称空间
# 2. 执行文件spam.py,将执行过程中产生的名字都放到模块的名称空间中
# 3. 在当前执行文件中直接拿到一个名字,该名字就是执行模块中相对应的名字的
from spam import money,read1,read2,change
money=200
print(money)
read1=123
read1()
read2()
change()
print(money)
# 总结from...import...
# 优点: 使用时,无需再加前缀,更简洁
# 缺点: 容易与当前名称空间中的名字冲突
# *代表从被导入模块中拿到所有名字(不推荐使用)
from spam import money,read1,read2,change
from spam import * # __all__ = ['money','read1']
print(money)
print(read1)
print(read2)
print(change)
# 起别名
from spam import read1 as r1
r1()
模块的循环导入
# m1.py # 模块一
# 错误示范
'''
print('正在导入m1')
from m2 import y #第一次导入m2
x='m1'
'''
# 解决方案一: 把循环导入的语句放到名字定义的后面
print('正在导入m1')
x='m1'
from m2 import y #第一次导入m2
# 解决方案二: 将循环导入语句放到函数内
print('正在导入m1')
def f1():
from m2 import y,f2 #第一次导入m2
print('m1.f1---->y: ',y)
f2()
x='m1'
# m2.py # 模块二
# 错误示范
'''
print('正在导入m2')
from m1 import x
y='m2'
'''
# 解决方案一: 把循环导入的语句放到名字定义的后面
print('正在导入m2')
y='m2'
from m1 import x
# 解决方案二: 将循环导入语句放到函数内
print('正在导入m2')
def f2():
from m1 import x
print('m2.f2--->x: ',x)
y='m2'
# run.py # 运行主程序
# import m1 # 第一次导入
# 验证解决方案一:把循环导入的语句放到名字定义的后面
'''
正在导入m1
正在导入m2
'''
# print(m1.x)
# print(m1.y)
# 验证解决方案二:将循环导入语句放到函数内
import m1 # 第一次导入
'''
正在导入m1
'''
# print(m1.x)
# print(m1.f1)
m1.f1()
'''
正在导入m2
m1.f1---->y:m2
m2.f2--->x:m1
'''
区分python文件的两种用途
# 当文件被执行时:__name__=='__main__'
# 当文件被导入时:__name__=='模块名'
# m1.py
def f1():
print('f1')
def f2():
print('f2')
print(__name__)
if __name__ == '__main__':
f1()
f2()
# 运行结果:
# __main__
# f1
# f2
# run.py
import m1 # 运行结果:m1
模块的搜索路径
# 模块搜索路径的优先级
# 1. 内存中已经加载过的
# 2. 内置模块
# 3. sys.path # 第一个值是当前执行文件所在的文件夹
import sys
print(sys.path) # 打印当前运行文件路径并向上层寻找的文件夹名列表
# 如果无法导入模块(原因是在路径中没有搜索到),有两种解决方案:
# 方案一:
import sys
sys.path.append(r'D:\document\python\egon视频\day16\代码\03 模块的搜索路径1\dir1')
print(sys.path)
import m1
m1.f1()
# 方案二:
from dir1 import m1 # 寻找一层
m1.f1()
from dir1.dir2 import m2 # 寻找两层
m2.f2()
# m2.py
def f2():
print('m2.f2')
# m1.py
import m2
from dir1 import m2 # 所有被导入的模块再去导入其他模块,参考的都是执行文件的sys.path
def f1():
print('from f1')
m2.f2()
# run.py
# 环境变量是以当前执行文件为准的
# ******强调:所有被导入的模块参照环境变量sys.path都是以执行文件为准的
import sys
sys.path.append(r'D:\脱产三期视频\day16\04 模块的搜索路径2\dir0')
from dir1 import m1 # 从列表中的第一个文件开始找dir1
m1.f1()
绝对导入和相对导入
# 绝对导入: 以执行文件的sys.path为起始点开始导入,称之为绝对导入
# 优点: 执行文件与被导入的模块中都可以使用
# 缺点: 所有导入都是以sys.path为起始点,导入麻烦
# 相对导入: 参照当前所在文件的文件夹为起始开始查找,称之为相对导入
# 符号: .代表当前所在文件的文件加,..代表上一级文件夹,...代表上一级的上一级文件夹
# 优点: 导入更加简单
# 缺点: 只能在导入包中的模块时才能使用,不能在执行文件中用
# 执行文件中只能用绝对导入
time 模块
"""
time模块
与时间相关的功能
在python中 时间分为3种
1.时间戳 timestamp 从1970 1 月 1日 到先在的秒数 主要用于计算两个时间的差
2.localtime 本地时间 表示的是计算机当前所在的位置
3.UTC 世界协调时间
时间戳 结构化 格式化字符
"""
import time
# 获取时间戳 返回浮点型
print(time.time())
# 获取当地时间 返回的是结构化时间
print(time.localtime())
# 获取UTC时间 返回的还是结构化时间 比中国时间少8小时
print(time.gmtime())
# 将获取的时间转成我们期望的格式 仅支持结构化时间
print(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()))
# 将格式化字符串的时间转为结构化时间 注意 格式必须匹配
print(time.strptime("2018-08-09 09:01:22","%Y-%m-%d %H:%M:%S"))
# 时间戳 转结构化
print(time.localtime(time.time()))
# 结构化转 时间戳
print(time.mktime(time.localtime()))
# sleep 让当前进程睡眠一段时间 单位是秒
# time.sleep(2)
# print("over")
# 不太常用的时间格式
print(time.asctime())
print(time.ctime())
datetime 模块
"""
datetime
python实现的一个时间处理模块
time 用起来不太方便 所以就有了datetme
总结 datetime相比time 更灵活 更本土化
timedelta表示时间差
两个时间差可以 +-*/
时间差和datetime 可以+-
"""
import datetime
# 获取时间 获取当前时间 并且返回的是格式化字符时间
print(datetime.datetime.now())
# 单独获取某个时间 年 月
d = datetime.datetime.now()
print(d.year)
print(d.day)
# 手动指定时间
d2 = datetime.datetime(2018,8,9,9,50,00)
print(d2)
# 计算两个时间的差 只能- 不能加+
print(d - d2)
# 替换某个时间
print(d.replace(year=2020))
# 表示时间差的模块 timedelta
print(datetime.timedelta(days=1))
t1 = datetime.timedelta(days=1)
t2 = datetime.timedelta(weeks=1)
print(t2 - t1)
# 时间差可以和一个datetime进行加减
print(d + t2)
random 模块
"""
random 随机数相关模块
random 0-1 开闭
randint 0 - 3 开开
randrange 0 - 3 开闭
choice [1,2,32,3,2,"哈哈"] 随机选⼀个
sample([1,"a",["c","d"]],2) 随机选指定个数
uniform(1,3) 闭闭 浮点
shuffle(列表) 打乱顺序
"""
import random
# 0 - 1 随机浮点 不包含1
print(random.random())
# randint 0 - 3 开开
print(random.randint(1,3))
# randrange 0 - 3 开闭
print(random.randrange(1,3))
# choice [1,2,32,3,2,"哈哈"] 随机选⼀个
print(random.choices((1,2,3)))
# sample([1,"a",["c","d"]],2) 随机选指定个数
print(random.sample([1,2,3],2))
# shuffle(列表) 打乱顺序
l = [1,2,3,4,5]
print(random.shuffle(l))
print(l)
# uniform(1,3) 闭闭 浮点
print(random.uniform(1,2))
# 生产验证码 整形和字符(全大写)随机组成 可以指定长度
def make_code(i):
res = ""
for j in range(i):
# 随机0到9
num = str(random.randint(0,9))
c = chr(random.randint(65,90))
s = random.choice([num,c])
res += s
return res
print(make_code(4))
# example
import random
print("掌声有请:第%s排 第%s位童鞋" % (random.randint(1,10),random.randint(1,8)))
shutil 模块
"""
shutil 模块
用于简化文件操作 (文件的高级操作)
常用方法
copy
move
rm
make_archive
"""
import shutil
import zipfile,tarfile
#shutil.copyfileobj(open("a.txt","r",encoding="utf-8"),open("b.txt","w",encoding="utf-8"),length=1024)
# 利用shutil来创建压缩文件 仅支持 tar 和zip格式 内部调用zipFIle tarFIle模块实现
# shutil.make_archive("test","zip",root_dir="D:\脱产三期视频\Day17\代码")
# 解压zip
# z = zipfile.ZipFile(r"D:\脱产三期视频\Day17\test.zip")
# z.extractall()
# z.close()
# 解压tar
# t = tarfile.open(r"D:\脱产三期视频\Day17\test.tar")
# t.extractall()
# t.close()
# t = tarfile.open(r"D:\脱产三期视频\Day17\mytar.tar","w")
# t.add(r"D:\脱产三期视频\Day17\1_datetime_test.py")
# t.close()
sys 模块
"""
sys模块
系统相关
一般用于设计脚本程序
常用方法
argv 获取cmd输入的参数
"""
import sys
print(sys.argv)
print(sys.platform)
# print(sys.exit(0))
# 模拟进度条
"""
当程序要进行耗时操作时例如 读写 网络传输
需要给用户提示一个进度信息
"[******** ]"
"[********* ]"
"[************ ]"
"[****************]"
"""
# print("[* ]")
# print("[** ]")
print("[%-10s]" % ("*" * 1))
print("[%-10s]" % ("*" * 2))
print("[%-10s]" % ("*" * 3))
print("[%-10s]" % ("*" * 4))
# %的一些规范
# print("%-%ds" % (30,"1"))
# # %-30s % * %-30s
# # %%-%ds % 20
# # %-20s % "1212"
# print("%%")
# print(("%%-%ds" % 20) % "*" )
# 比例 0 - 1 0.5
def progress(percent,width=30):
percent = percent if percent <= 1 else 1
text = ("\r[%%-%ds]" % width) % ("*" * int((width * percent)))
text = text + "%d%%"
text = text % (percent * 100)
print( text , end="")
# progress(0.5)
# 模拟下载
# 文件大小
import time
file_size = 10240
# 已经下载大小
cur_size = 0
while True:
time.sleep(0.5)
cur_size += 1021
progress(cur_size / file_size)
if cur_size >= file_size:
print()
print("finish")
break
OS 模块
"""
OS模块
os表示操作系统相关
第一大块功能 就是围绕文件和目录的操作
"""
import os,sys
# 获取当前文件夹路径
print(os.getcwd())
# 获取当前文件路径
print(__file__)
print(os.stat("D:\脱产三期视频\Day17\datetime_test.py"))
print(sys.platform)
print(os.name)
# 获取当前文件目录
print(os.system("dir"))
# 获取系统环境变量
print(os.environ)
# path模块
# 绝对路径
print(os.path.abspath(r"bbb.txt"))
# 连接
print(os.path.join("C:","users","aaa.txt"))
# 规范化
print(os.path.normcase(r"/a/b/CSD"))
print(os.path.normpath(r"a\b\c\d\.."))
# 获取项目主目录
print(os.path.dirname(os.path.dirname(__file__)))
print(os.path.normpath(os.path.join(os.getcwd(), os.pardir)))
pickle 模块
"""
pickle模块:
作用于序列化
序列化就是将内存中的数据持久化到硬盘(二进制)
回顾:使用文件读写也能完成把数据持久化存储,但是有局限性,当数据比较复杂时用起来就很麻烦
例如:需要把一个字典存储到硬盘中 先转成字符串 写入 读取为字符串 转为原始的格式
所以就有了pickle
1.能将所有python中的数据序列化 int float str dic list tuple set bool
2.反序列化 将之前序列化的数据 在恢复成python的数据格式
pickle产生的数据,只能由python读取 (跨平台性差)
今后你开发程序不可能就是单机程序,你需要和其他设备、其他平台交换数据
我们需要找到一种通用的数据格式 让各个平台都能识别
"""
users = {"name":"yyh","age":20,"hobbies":["打豆豆","飘"]}
# f = open("a.txt","wt",encoding="utf-8")
# f.write(str(users))
# f.close()
import pickle
print(pickle.dumps(users))
# 序列化
f = open("p.txt","wb")
f.write(pickle.dumps(users))
f.close()
# 反序列化
f = open("p.txt","rb")
print(pickle.loads(f.read()))
print(type(pickle.loads(f.read())))
f.close()
# 序列化(另一种写法)
pickle.dump(users,open("pp.txt","wb"))
# 反序列化(另一种写法)
print(pickle.load(open("pp.txt","rb")))
json 模块
"""
pickle产生的数据 只能由python读取 (跨平台性差)
今后你开发程序不可能就是单机程序 你需要和其他设备 其他平台 交换数据
我们需要找到一种通用的数据格式 让各个平台都能识别
json模块:
用于处理json格式数据的模块
json 全称:JavaScrip Object Notation js的对象表示法
所以json能支持的数据类型就是js支持数据类型
json格式标准
能存储的有 str int float dic list bool
案列:
要求:数据的最开始和最末尾 必须是{} []
{"name":"yyh"}
json是一种通用的数据交换格式 目前主流的语言都能够轻松解析
注意: 在使用json格式的时候 数据类型必须按照要求来写,并且,不支持python的元组、True/Flase、''、'''。
常用方法
序列化
dump 处理文件
dumps 处理字符串
反序列化
load 处理文件
loads 处理字符串
"""
# 将python格式的数据序列化为json格式 python中的任何类型都能被转化为json格式,只不过表现形式不同
import json
users = {'name':"音乐会","age":20,"hobbies":("music","movies")}
print(json.dumps(users))
print(type(json.dumps(users))) #str
json.dump(users,open("users.json","wt",encoding="utf-8"))
# json的反序列化
jsonstr = json.load(open("users.json","r",encoding="utf-8"))
print(jsonstr)
总结
"""
time
时间转换 ****
datetime
获取时间 ***
os
操作系统的文件路和目录
os.path *****
sys
解释器相关 用于设计脚本程序 ***
pickle
python本地序列化方式 比较局限 **
json
通用的数据交换格式 使用起来挺简单 *****
shutil
文件相关的高级操作 ***
random
随机数相关 简单 ****
"""