第六章 模块
6.1前言
- 什么是模块
- py文件 写好了的 对程序员直接提供某方面功能的文件
- import
- rom import 名字
- 什么是包
- 文件夹 存储了多个py文件的文件夹
- 如果导入的是一个包,这个包里的模块默认是不能用的
- 导入一个包相当于执行
__init__
py文件中的内容
6.1 模块初步(import)
# import 模块名 # 调用py的内置模块,
6.1.1 sys.模块
### py 解释器相关的数据
import sys
sys.getrefcount() # 获取一个值的引用次数,用得少,不重要
a = [11,22,33]
b = a
print(sys.getrefcount(a))
###sys.getrecursionlimit()
print(sys.getrecursionlimit()) # 1000次,python默认支持的递归数量.实际使用用个人的电脑配置有关
###sys.stdout.write --> print (进度)
import time
for i in range(100):
msg = '进度条跑到%s%%\r' %i # \r 光标回到当前行的起始位置(不是覆盖.,是清空)
print(msg , end = '')
time.sleep(0.5) # 暂停0.5s后再运行
### sys.agrv #### 获取用户执行脚本时,传入的参数。得到的是一个列表,第一个元素是脚本文件.py
## Sys.argv[ ]其实就是一个列表,里边的项为用户输入的参数,关键就是要明白这参数是从程序外部输入的,而非代码本身的什么地方,要想看到它的效果就应该将程序保存了,从外部来运行程序并给出参数。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
让用户执行脚本传入要删除的文件路径,在内部帮助用将目录删除。
C:\Python36\python36.exe D:/code/s21day14/7.模块传参.py D:/test
C:\Python36\python36.exe D:/code/s21day14/7.模块传参.py
"""
import sys
# 获取用户执行脚本时,传入的参数。
# C:\Python36\python36.exe D:/code/s21day14/7.模块传参.py D:/test
# sys.argv = [D:/code/s21day14/7.模块传参.py, D:/test]
path = sys.argv[1]
# 删除目录
import shutil
shutil.rmtree(path)
-
sys.argv
-
sys.path # 默认Python去导入模块时,会按照sys.path中的路径挨个查找。 ---> 本质是列表
-
sys.exit( 0 ) 是正常退出 sys.exit( 1) 异常退出
-
sys.modules
sys.modules # 存储了当前程序中用到的所有模块,反射本文件中的内容 sys.modules[__name__]---->指向本文件 # '__main__': <module '__main__' from 'D:/code/day24/1.内容回顾.py'>
6.1.2 os 模块
和操作系统相关的数据。
-
os.path.exists(path) , 如果path存在,返回True;如果path不存在,返回False
-
os.stat('20190409_192149.mp4').st_size , 获取文件大小
-
os.path.getsize()-->获取文件大小
-
os.path.abspath() , 获取一个文件的绝对路径
import os # 1. 读取文件大小(字节) file_size = os.stat('20190409_192149.mp4').st_size # 2.一点一点的读取文件 read_size = with open('20190409_192149.mp4',mode='rb') as f1,open('a.mp4',mode='wb') as f2: while read_size < file_size: chunk = f1.read(1024) # 每次最多去读取1024字节 f2.write(chunk) read_size += len(chunk) val = int(read_size / file_size * 100) print('%s%%\r' %val ,end='')
import os
os.path.exists(path) #如果path存在,返回True;如果path不存在,返回False.文件路径
os.stat('20190409_192149.mp4').st_size # 获取文件大小(字节大小)
os.path.abspath() # 获取一个文件的绝对路径
os.path.dirname # 获取路径的上级目录(文件夹)
-
os.path.join ,路径的拼接
import os path = "D:\code\s21day14" # user/index/inx/fasd/ v = 'n.txt' result = os.path.join(path,v) print(result) # # D:\code\s21day14\n.txt result = os.path.join(path,'n1','n2','n3') print(result) # D:\code\s21day14\n1\n2\n3
-
os.listdir , 查看一个目录下所有的文件【第一层】
import os result = os.listdir(r'D:\code\s21day14') # r,在字符创=串前面,转义符,把\n\t\r当做字符串. for path in result: print(path)
-
os.walk , 查看一个目录下所有的文件【所有层】
import os result = os.walk(r'D:\code\s21day14') for a,b,c in result: # a,正在查看的目录 b,此目录下的文件夹 c,此目录下的文件 for item in c: path = os.path.join(a,item) print(path) # 还有其他很多用途 获取文件夹大小,即遍历文件夹,将所有文件大小加和。遍历文件夹使用os.walk函数 os.walk()可以得到一个三元tupple(dirpath, dirnames, filenames), 1、第一个为起始路径, 2、第二个为起始路径下的文件夹, 3、第三个是起始路径下的文件。 其中dirpath是一个string,代表目录的路径,dirnames是一个list,包含了dirpath下所有子目录的名字。filenames是一个list,包含了非目录文件的名字。这些名字不包含路径信息,如果需要得到全路径,需要使用os.path.join(dirpath, name). 复制代码 import os from os.path import join, getsize def getdirsize(dir): size = 0 for root, dirs, files in os.walk(dir): size += sum([getsize(join(root, name)) for name in files]) return size if __name__ == '__main__': filesize = getdirsize('E:\chengd') print('There are %.3f' % (filesize / 1024 / 1024 ), 'Mbytes in E:\\chengd') 执行结果: There are 4747.763 Mbytes in E:\chengd
-
转义符的使用
v1 = r"D:\code\s21day14\n1.mp4" (推荐) print(v1) v2 = "D:\\code\\s21day14\\n1.mp4" print(v2)
-
os.makedirs,创建目录和子目录--->比makedir 好用,只能创建一层目录
import os file_path = r'E:\小莫的黄片库\绝对不能偷看\请输入密码\****.MP4' file_folder = os.path.dirname(file_path) if not os.path.exists(file_folder): os.makedirs(file_folder) with open(file_path,mode='w',encoding='utf-8') as f: f.write('asdf')
-
os.rename 重命名
import os os.rename('db','sb') # 原文件 ,现文件
6.1.3 shutil 模块
-
删除目录
import shutil shutil.rmtree(path)
import shutil
##删除目录(只能是文件夹)
shutil.rmtree('test')
## 重命名
shutil.move(old,new) ,移动文件
##压缩文件
shutil.make_archive('压缩后文件名可以加文件路径','压缩格式zip等等','被压缩的文件/文件夹')
shutil.make_archive('zzh','zip','D:\code\s21day16\lizhong')
##解压文件
shutil.unpack_archive('要解压的文件夹',extract_dir=r'D:\code\xxxxxx\xxxx',格式:'zip')
# 解压的路径
shutil.unpack_archive('zzh.zip',extract_dir=r'D:\code\xxxxxx\xxxx',format='zip')
举例
import shutil
shutil.rmtree('4567') # 删除目录(只能是文件夹)
shutil.move(前文件名,后文件名) # 重命名/移动,看后一个文件是文件夹还是文件名
shutil.make_archive(r'E:\159','zip','456') # 把py文件目录的456压缩到E:\159,即E盘的根目录下159.zip
shutil.unpack_archive('159.zip',r'F:\159\158','zip') # 把159.zip解压文件到F:\159\158,解压格式是zip.
6.1.4 json 模块
-
用法
-
son的本质(为着各程序间信息的传递而规定的一种通用格式)
- 本质是一个字符串(看起来像[],{},int/ bool )
- 最外层必须是list/dict
- 如果包含字符串,必须双引号--->其他程序字符串只识别双引号
用法
import json # 序列化,将python的值转换为json格式的字符串。 # v = [12,3,4,{'k1':'v1'},True,'asdf'] # v1 = json.dumps(v) # print(v1) json.dumps() ---->返回值是json格式--->字符串 # 反序列化,将json格式的字符串转换成python的数据类型 # v2 = '["alex",123]' # print(type(v2)) # v3 = json.loads(v2) # print(v3,type(v3)) json.loads() ---->返回值是python能识别的格式,外层一定是[]或{}
python与json的对照表
+-------------------+---------------+ | Python | JSON | +===================+===============+ | dict | object | +-------------------+---------------+ | list, tuple | array | +-------------------+---------------+ | str | string | +-------------------+---------------+ | int, float | number | +-------------------+---------------+ | True | true | +-------------------+---------------+ | False | false | +-------------------+---------------+ | None | null | +-------------------+---------------+
-
-
-
dumps 把python数据转换为json型的字符串 序列化
-
loads 把json字符串转换为python能够识别的数据类型 反序列还
-
注意 :若字典或列表中有中文,序列化是想要保留中文显示
v = {'k1':'alex','k2':'李杰'} #e nsure_ascii=False import json val = json.dumps(v,ensure_ascii=False) print(val)
-
dump(内容,文件句柄) 有2个参数
import json v = {'k1':'alex','k2':'李杰'} f = open('x.txt',mode='w',encoding='utf-8') val = json.dump(v,f) print(val) f.close() ## Json.dump()这个方法:它在底层做了两件事,一件事是将对象(列表)转换为字符串,第二件事是转换## 成功以后,将转换后的数据写入到文件中。
-
load
import json v = {'k1':'alex','k2':'李杰'} f = open('x.txt',mode='r',encoding='utf-8') data = json.load(f) f.close() print(data,type(data)) # 做了两件事,一件事:先来读取文件里的内容,第二件事是:将读取出来的内容进行数据类型的转换。
-
6.1.5 pickle 模块
-
json,优点:所有语言通用;缺点:只能序列化基本的数据类型 list/dict/int...
-
pickle,优点:python中所有的东西都能被他序列化(除了socket对象);缺点:序列化的内容只有python认识。
import pickle ###################### dumps / loads #######################3 v = {1,2,3,4} val = pickle.dumps(v) print(val) data = pickle.loads(val) print(data,type(data)) ######################## dump / load 用法和json类似,这里不再赘述#### ###################################################### # 序列化 把其他数据类型转换成 str/bytes类型-->dump/dumps # 反序列化 str/bytes类型 转换回去 -->load/loads 所有编程语言 json 所有的语言都支持 # json格式 : # 1.所有的字符串都是双引号 # 2.最外层只能是列表或者字典 # 3.只支持 int float str list dict bool # 4.存在字典字典的key只能是str # 5.不能连续load多次 # pickle 只支持python语言 # 1.几乎所有的数据类型都可以写到文件中 # 2.支持连续load多次
6.1.6time 和 datetime 模块
-
time模块
time.time() 时间戳,显示的是1970.1.1.凌晨0.00到现在经过的秒数,得到的是float数据类型
time.sleep() 程序运行等待的秒数
time.timezone : 属 性time.timezone是当地时区(未启动夏令时)距离格林威治的偏移秒数(>0,美洲;<=0大部分欧洲,亚洲,非洲) ,和电脑设置的逝去==时区有关
-
datetime 模块
#!/usr/bin/env python # -*- coding:utf-8 -*- import time from datetime import datetime,timezone,timedelta # ######################## 获取datetime格式时间 ############################## """ v1 = datetime.now() # 当前本地时间 print(v1) tz = timezone(timedelta(hours=7)) # 当前东7区时间 v2 = datetime.now(tz) print(v2) v3 = datetime.utcnow() # 当前UTC时间 print(v3) """ # ######################## 把datetime格式转换成字符串 ############################## # v1 = datetime.now() # print(v1,type(v1)) # val = v1.strftime("%Y-%m-%d %H:%M:%S") # print(val) # ######################## 字符串转成datetime ############################## # v1 = datetime.strptime('2011-11-11','%Y-%m-%d') # print(v1,type(v1)) # ######################## datetime时间的加减 ############################## # v1 = datetime.strptime('2011-11-11','%Y-%m-%d') # v2 = v1 - timedelta(days=140) # date = v2.strftime('%Y-%m-%d') # print(date) # ######################## 时间戳和datetime关系 ############################## # ctime = time.time() # print(ctime) # v1 = datetime.fromtimestamp(ctime) # print(v1) # v1 = datetime.now() # val = v1.timestamp() # print(val)
6.1.7 collections 模块
# 调用模块,字典有序
from collections import OrderedDict
info = OrderedDict()
# 有序字典
OrderDict()
# 字典的另一种写法
dict([(1,2),(3,4),(5,6)]) # dict化 列表套元组
# namedtuple,顾名思义,可命名元组
Course = namedtuple('Course',['name','price','teacher'])
python = Course('python',19800,'alex')
print(python)
print(python.name)
print(python.price)
# 创建一个类,这个类没有方法,所有属性的值都不能修改
# deque 双端队列
# defaultDict 默认字典,可以给字典的value设置一个默认值
6.1.8 hashlib 模块 摘要算法
-
将密码加密
# import 模块名 # 调用py的内置模块, # PY调用hashlib模块对用户的密码进行加密,hashlib模块有很多种加密方式.这里选用MD5加密 import hashlib def md5(arg): # 加密函数 hash = hashlib.md5('dengyxiin'.encode('utf-8')) # 加盐,避免给黑客撞库得到密码. hash.update(arg.encode('utf-8')) return hash.hexdigest() # 返回加密的md5,<----->t = hash.hexdigest();return t def register(user,pwd): # 注册函数,参数为用户名和密码 with open('data.txt','a',encoding='utf-8') as file: # 追加模式写入文件 file.write(user+'|'+md5(pwd)+'\n') #用户名和密码用竖杠隔开,方便以后找寻 def login(user,pwd): # 登录函数 with open('data.txt','r',encoding='utf-8') as file: # 以只读模式打开文件,遍历文件, for line in file: line = line.strip() line = line.split('|') if user == line[0] and md5(pwd) == line[1]: #遍历存储登录数据的文件,看能否比对的上. return True
-
密文验证
-
验证文件的一致性hashlib
import hashlib hash = hashib.md5() hash.update() # 无数次update,把大文件分割update进去即可. t = hash.hexdigest() print(t) # md5.update('hello'.encode()) # md5.update(',wusir'.encode()) # 46879507bf541e351209c0cd56ac160e # 46879507bf541e351209c0cd56ac160e 分批次update进去,最终结果相同
6.1.9 random模块(应用)
import random
random.unifom(1,5) # 取1-5间的小数
val = random.choice(序列) # -->从序列中随机抽取一个元素
val22 = ramdom.sample(序列,n) # -->从序列中随机抽取n个元素
shuffle(序列) # 打乱,洗牌
import random # 调用随机数函数
def get_random_code(length=6):
data = []
for i in range(length):
v = random.randint(65,90) # 65-90对应的是ABC-----Z
data.append(chr(v)
return ''.join(data)
code = get_random_code()
print(code)
6.1.10 getpass 模块
# 让密码在键入的时候隐藏
import getpass
pwd = getpass.getpass('请输入密码:')
if pwd == '123456789':
print('输入正确')
import time
print(time.time())
time.sleep(2) # --> 睡 2秒
6.2 模块分类
6.2.1内置模块
-
random
-
hashlib
-
getpass
-
time
-
copy
-
os
- os.makedirs
- os.path.join
- rename 重命名
- os.path.dirname
- os.path.abspath
- os.path.exists
- os.stat('文件路径')
- os.listdir
- os.walk
-
sys
- sys.argv
- sys.path
-
shutil
-
json
-
json 模块
json的本质(为着各程序间信息的传递而规定的一种通用格式)
- 本质是一个字符串(看起来像[],{},int/ bool )
- 最外层必须是list/dict
- 如果包含字符串,必须双引号--->其他程序字符串只识别双引号
用法
import json # 序列化,将python的值转换为json格式的字符串。 # v = [12,3,4,{'k1':'v1'},True,'asdf'] # v1 = json.dumps(v) # print(v1) json.dumps() ---->返回值是json格式--->字符串 # 反序列化,将json格式的字符串转换成python的数据类型 # v2 = '["alex",123]' # print(type(v2)) # v3 = json.loads(v2) # print(v3,type(v3)) json.loads() ---->返回值是python能识别的格式,外层一定是[]或{}
python与json的对照表
+-------------------+---------------+ | Python | JSON | +===================+===============+ | dict | object | +-------------------+---------------+ | list, tuple | array | +-------------------+---------------+ | str | string | +-------------------+---------------+ | int, float | number | +-------------------+---------------+ | True | true | +-------------------+---------------+ | False | false | +-------------------+---------------+ | None | null | +-------------------+---------------+
-
-
内置模块补充
-
sys
-
6.2.2第三方模块
-
下载和安装
pip的使用
-
# 把pip.exe 所在的目录添加到环境变量中。 pip install 要安装的模块名称 # pip install requests
-
python36 -m pip install --upgrade pip 语句的使用
-
python3 -m pip install -U --force-reinstall pip 若pip更新失败,则如此
-
网络不好一直抱超时错误的话可以换一个源,粘贴下边代码运行
pip3 install xlrd -i http://pypi.douban.com/simple/ —trusted-host pypi.douban.com注意 : 这里的pip / pip3 都是自己定义的环境变量
-
安装完成后,如果导入不成功。
- 重启pycharm。
- 安装错了。
-
-
你了解的第三方模块:
- xlrd
- requests
6.2.3自定义模块
-
自定义模块的导入
xxxx.py # 自定义模块,实现某功能
def func(): print(123) #实现打印123
x2.py
# 在x2.py中希望调用xxxx.py的函数 ####1. xxxx.py 和 x2.py 在同一文件夹下 import xxxx xxxx.func() ####2. 不在同一文件夹下 import sys sys.path.append('xxxx.p文件的绝对路径') import xxxx xxxx.func() #####在cmd中运行x2.py文件 python3 x2.py
-
-
模块和执行的py在同一目录,且需要调用很多函数
# 在1.py文件中调用xxxx.py import xxxx xxxx.func() #调用函数 xxxx.func2() #调用函数2
-
包和执行的py在同一目录
from 包 import jd模块 jd模块.func() # 调用包内的jd模块的所有函数--- from 包.jd模块 import func func() #调用jd的func函数 ################################ from 包.jd模块 import func , show ,func2 #可以用都逗号连接 func() show() func2() ################################# from 包.jd模块 import * # 调用包.jd模块的全部功能
-
- 模块和要执行的py文件在同一目录 且 需要 模块中的很多功能时,推荐用: import 模块
- 其他推荐:from 模块 import 模块 模块.函数()
- 其他推荐:from 模块.模块 import 函数 函数()
-
注意 : 要从其他路径调用模块时的用法
import sys sys.path.append(r'D:\自建模块包\项目1模块') # ---->把路径添加到python寻找模块时会去寻找的路径中,在调用模块 import xxxx # xxxx.py在'D:\自建模块包\项目1模块'目录下 xxxx.func() # sys,path 本质是一个列表,是py解释器寻找模块时会去寻找的路径.path指定用于模块搜索路径的字符串列表。
-
模组调用
-
import
- import 模块1 模块1.函数()
- import 模块1.模块2.模块3 模块1.模块2.模块3.函数()
-
from xx import xxx
- from 模块.模块 import 函数 函数()
- from 模块.模块 import 函数 as f f()
- from 模块.模块 import * 函数1() 函数2()
- from 模块 import 模块 模块.函数()
- from 模块 import 模块 as m m.函数()
- 特殊情况:
- import 文件夹 加载
__init__.py
- import 文件夹 加载
- from 文件 import *
-
注意:文件和文件夹的命名不能是导入的模块名称相同,否则就会直接在当前目录中查找。
-
6.3 模块导入(重点)
6.3.1多次导入模块只加载一次--->单例模式
# 文件名 --> jd.py
print(123)
###################################
import jd # 第一次加载:会加载一遍jd中所有的内容。
import jd # 由已经加载过,就不在加载。 # 只打印一次123
print(456)
# 重加载 importilb.reload
import importlib
import jd
importlib.reload(jd)
print(456) # 打印2次123 和456
**额外 : **通过模块导入的特性也可以实现单例模式
# jd.py
class Foo(object):
pass
obj = Foo()
############################
# app.py
import jd
print(jd.obj) # 单例模式
6.3.2日志操作loggin模块
-
作用:
- 记录日志的
- 用户 :查看操作记录
- 程序员 :
- 统计用
- 故障排除
- 记录错误,做代码优化
-
基本应用( 默认的,无法更改编码,win编码不同乱码,不推荐)
import logging logging.basicConfig( filename='cmdb1.log', format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S %p', level=logging.ERROR ) # 默认的,无法更改编码,win编码不同乱码,不推荐 logging.error(msg,exc_info=True) # exc_info=True,打印错误日志是把栈信息打印出来 # 使用方便 # 不能实现 编码问题;不能同时向文件和屏幕上输出 # logging.debug,logging.warning
-
日志处理的本质(Logger/FileHandler/Formatter)
#复杂 # 创建一个logger对象 # 创建一个文件操作符 # 创建一个屏幕操作符 # 创建一个格式 # 给logger对象绑定 文件操作符 # 给logger对象绑定 屏幕操作符 # 给文件操作符 设定格式 # 给屏幕操作符 设定格式 # 用logger对象来操作 import logging logger = logging.Logger('xxxxxx', level=logging.ERROR) logger = logging.Logger('邓益新',level=10) # logger = logging.getLogger('boss') ,无法设置level fh = logging.FileHandler('log.log','a',encoding = 'utf-8') sh = logging.StreamHandler() formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s',datefmt = '%Y-%m-%d %H-%M-%S',) fh.setFormatter(formatter) sh.setFormatter(formatter) logger.addHandler(fh) logger.addHandler(sh) logger.warning('message') # file_handler2 = logging.FileHandler('x2.log', 'a', encoding='utf-8') # fmt2 = logging.Formatter(fmt="%(asctime)s: %(message)s") # file_handler2.setFormatter(fmt2) logger.error('你好')
-
推荐处理方式
import logging file_handler = logging.FileHandler(filename='x3.log', mode='a', encoding='utf-8',) logging.basicConfig( format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S %p', handlers=[file_handler,], level=logging.ERROR ) logging.error('你好')
-
日志处理 + 分割
import logging from logging import handlers file_handler = handlers.TimedRotatingFileHandler(filename='x3.log', when='s', interval=5, encoding='utf-8') logging.basicConfig( format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S %p', handlers=[file_handler,], level=logging.ERROR ) logging.error('你好') # when = ''取 S M H D W,不区分大小写
-
在应用日志时,如果想要保留异常的堆栈信息。
logging.error('你好',exc_info=True) # 即可
新人上路,请多多批评指正