模块

模块

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
        随机数相关   简单          ****
"""
上一篇:Python-7-字典方法


下一篇:模块与包