python_模块
一、什么是模块?
别人写好的功能放在一个py文件里
一般有:内置模块,第三方模块,自定义模块
二、序列化模块
序列:列表,元祖,字符串,bytes
什么是序列化?
把一个数据类型转化成字符串,bytes类型就是序列化
为什么要序列化?
当你需要把一个数据类型放在文件文件时
当你需要把一个数据类型通过网络传输时
1、json模块
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import json dic = {'name':'张三','age':18} str_dic = json.dumps(dic,ensure_ascii=False) print(str_dic) str_dic1 = json.loads(str_dic) print(str_dic1) li = [1,3,'a','sad'] str_li = json.dumps(li) str_li1 = json.loads(str_li) print(str_li) print(str_li1) # 操作文件 ensure_ascii=False 中文转码 with open('json_file.txt','w',encoding='utf-8') as f: json.dump(dic,f) with open('json_file.txt',encoding='utf-8') as f1: print(json.load(f1))
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 可以多次向文件dump? 多次load吗? # 可以多次dump,但不能load info = {'name':'qwe','age':14} with open('json_file.txt','a',encoding='utf-8') as f: json.dump(info,f,ensure_ascii=False) with open('json_file.txt','r',encoding='utf-8') as f: json.load(f) def my_dumps(dic): with open('json_file.txt','a',encoding='utf-8') as f: str_dic = json.dumps(dic) f.write(str_dic+'\n') dic = {'name':'ald','age':12} # my_dumps(dic) with open('json_file.txt','r',encoding='utf-8') as f: for line in f: dic = json.loads(line.strip()) print(dic)
json格式化
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# json格式化 import json data = {'username':['小明','小黑'],'sex':'male','age':16} data_json = json.dumps(data,ensure_ascii=False,indent=4,sort_keys=True,separators=(',',':')) print(data_json)
json的优点:
所有的语言都通用
缺点:
只支持非常少的数据类型
对数据类型的约束很苛刻
字典的key必须是字符串
只支持 :数字,列表,字符串,字典
2、pickle
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import pickle s1 = {'name':'wam',1:('a','b',3)} s2 = pickle.dumps(s1) print(s2) s3 = pickle.loads(s2) print(s3) class Course: def __init__(self,name,price): self.name = name self.price = price python = Course('python',19800) c1 = pickle.dumps(python) print(c1) c2 = pickle.loads(c1) print(c2.name,c2.price)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# pickle多次dump和多次load需要异常处理‘ import pickle dic = {'name':'xm','age':13} def my_dump(dic): with open('pickle_file.txt','ab') as f: pickle.dump(dic,f) # my_dump(dic) with open('pickle_file.txt','rb') as f1: while 1: try: print(pickle.load(f1)) except EOFError: break pickle操作文件必须以+b模式打开 在load的时候,如果这个要被load的内容所在的类不存在内存中,会报错
三、时间模块
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import time print(time.time()) #当前时间戳时间,浮点数为单位 print(time.localtime()) #结构化时间 print(time.strftime('%y-%m-%d %H:%M:%S')) #格式化时间 struct_time = time.localtime(3000000000) fmt_time = time.strftime('%Y-%m-%d %H:%M:%S',struct_time) print(fmt_time) fmt_time = time.strftime('%Y-%m-1') struc_time = time.strptime(fmt_time,'%Y-%m-%d') timestamp = time.mktime(struc_time) print(timestamp)
四、sys模块
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
sys模块是与python解释器交互的一个模块 print(sys.path) 一个模快能否被导入,就看这个模块所在的目录在不在sys.path中 内置模块和第三方扩展模块都不需要我们处理,sys.path可以直接访问 自定义模块的导入工作,需要自己手动的修改sys.path print(sys.argv) 执行脚本时带的参数会存放在sys.argv列表中 print(sys.modules[__name__]) print(sys.version) #获取python解释程序的版本信息 print(sys.platform) #返回操作系统平台名称
五、os模块
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import os os模块是与操作系统交互的一个接口 os.mkdir('packge') #生成单级目录 相当于shell中mkdir dirname os.makedirs('packge/app') #可生成多层递归目录 os.rmdir('packge') #删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname os.removedirs('packge/app') #若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推 os.remove('1.txt') #删除一个文件 os.rename('packge/112','packge/app') #重命名文件/目录 print(os.stat('F:\Demo\模块与包')) #获取文件,目录信息 st_atime: 上次访问的时间。 st_mtime: 最后一次修改的时间。 print(os.listdir()) #列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印 os.path print(os.path.abspath('app')) #返回path规范化的绝对路径 print(os.path.split(r'F:\Demo\模块与包\01_json模块.py')) #将path分割成目录和文件名以元组返回 print(os.path.dirname(r'F:\Demo\模块与包\08_os模块.py')) #返回path的目录。其实就是os.path.split(path)的第一个元素 print(os.path.basename(r'F:\Demo\模块与包\08_os模块.py')) 返回path最后的文件名。如果path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素 print(os.path.exists(r'F:\Demo\模块与包\08_os模块.py')) #如果path存在,返回True;如果path不存在,返回False print(os.path.isabs(r'F:\Demo\模块与包\08_os模块.py')) #如果path是绝对路径,返回True print(os.path.isfile(r'F:\Demo\模块与包\08_os模块.py')) #如果path是一个存在的文件,返回True。否则返回False print(os.path.isdir(r'F:\Demo\模块与包')) #如果path是一个存在的目录,则返回True。否则返回False print(os.path.join('/app/','lib/','script')) 合并目录 print(os.path.getatime(r'F:\Demo\模块与包\08_os模块.py')) #返回path所指向的文件或者目录的最后访问时间 print(os.path.getmtime(r'F:\Demo\模块与包\08_os模块.py')) #返回path所指向的文件或者目录的最后修改时间 print(os.path.getsize(r'F:\Demo\模块与包\08_os模块.py')) # 返回path的大小 os.system('dir') #运行shell命令,直接显示 print(os.popen('dir').read()) #运行shell命令,获取执行结果 print(os.getcwd()) #获取当前工作目录,即当前python脚本工作的目录路径 os.chdir(r'F:\Demo\模块与包') #改变当前脚本工作目录;相当于shell下cd print(os.getcwd())
六、collections模块
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# collections模块 # 根据基础数据类型又做了一些扩展 # 有序字典 # Counter 计数器 # 默认字典 # 可命名元祖 # 双端队列 from collections import Iterable from collections import Iterator dic = {'name':'zs'} print(isinstance(dic,Iterable)) #可迭代对象 print(isinstance(dic,Iterator)) #迭代器 dic = dict.fromkeys('abc',('a',1)) print(dic) dic = dict([(1,2),('a',3)]) print(dic) # 有序字典 from collections import OrderedDict dd = OrderedDict([(1,2),('a',3)]) for k in dd: print(k,dd[k]) print(dd) # 带有默认值的字典 from collections import defaultdict d = defaultdict(dict) d['b'] = 123 print(d['a'],d) d = {} print(d['a']) func = lambda :'default' d = defaultdict(func) print(d['a']) # 可命名元组 from collections import namedtuple birth = namedtuple('Struct_time',['year','month','day']) b1 = birth(2018,9,5) print(b1,type(b1)) print(b1.year) print(b1.month) print(b1.day) class A: pass a = A() print(type(A)) print(type(a)) # 可命名元组非常类似一个只有属性没有方法的类 # ['year','month','day']是对象属性名 # Struct_time是类 的名字 # 这个类最大的特点就是一旦实例化 不能修改属性的值 # 双端队列 from collections import deque l1 = [1,3,4] qu = deque(l1) qu.append('a') qu.append('b') qu.appendleft(0) qu.pop() qu.popleft() print(qu)
七、hashlib模块
主要用于登陆验证和文件的一致性校验
常用的算法有md5,sha等
算法是不可逆的
不同的字符串通过这个算法计算得到的密文始终是不同的
相同的算法,相同的字符串。获得密文始终是相同的。不同的语言,不同的环境(操作系统、版本、时间)
md5得到的是一组32位由16进制的字符串,sha得到的是一组40位由16进制的字符串
sha算法相比md5算法更复杂,计算时间越长,安全性更高
动态加盐
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def get_md5(name,pw): obj_md5 = hashlib.md5(name.encode('utf-8')) obj_md5.update(pw.encode('utf-8')) return obj_md5.hexdigest() def login(): name = input('<<<name:').strip() pw = input('<<<pw:').strip() with open('info.txt',encoding='utf-8') as f: for line in f: u_name,u_pw = line.strip().split('|') if name == u_name and u_pw == get_md5(name,pw): print('登陆成功') return
文件的一致性校验
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import os import hashlib def get_file_md5(file_path,buffer=1024): obj_md5 = hashlib.md5() file_size = os.path.getsize(file_path) with open(file_path,'rb') as f: while file_size: content = f.read(buffer) file_size -= len(content) obj_md5.update(content) return obj_md5.hexdigest()
八、configparser模块
配置文件目录
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import configparser config = configparser.ConfigParser() config["DEFAULT"] = {'ServerAliveInterval': '45', 'Compression': 'yes', 'CompressionLevel': '9', 'ForwardX11':'yes' } config['bitbucket.org'] = {'User':'hg'} config['topsecret.server.com'] = {'Host Port':'50022','ForwardX11':'no'} with open('example.ini', 'w') as configfile: config.write(configfile) 查找文件 import configparser config = configparser.ConfigParser() print(config.sections()) #[] config.read('example.ini') print(config.sections()) #['bitbucket.org', 'topsecret.server.com'] print('bitbucket.com' in config) #False print('bitbucket.org' in config) #True print(config['bitbucket.org']['user']) print(config['topsecret.server.com']['Host Port']) print(config['bitbucket.org']) #<Section: bitbucket.org> for key in config['bitbucket.org']: # 注意,有default会默认default的键 print(key) print(config.options('bitbucket.org')) # 同for循环,找到'bitbucket.org'下所有键 print(config.items('bitbucket.org')) # #找到'bitbucket.org'下所有键值对 print(config.get('topsecret.server.com','CompressionLevel')) #get方法Section下的key对应的value 增删改操作 import configparser config = configparser.ConfigParser() config.read('example.ini') config.add_section('path_info') config.remove_section('bitbucket.org') config.remove_option('topsecret.server.com','ForwardX11') print(config.sections()) # print(config.items('topsecret.server.com')) config.set('path_info','admin','user/login') config.set('topsecret.server.com','k1','xxx') config.write(open('new.ini','w'))
九、日志模块
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import logging logging.basicConfig(level=logging.DEBUG) #更改显示级别,默认是warning logging.debug('the debug...') #计算或者工作的细节 logging.info('the info...') #记录用户的信息,增删改操作 logging.warning('the warning...') #警告操作 logging.error('the error...') #错误操作 logging.critical('the critical...') #批判的,直接导致程序出错退出的 # 简单配置 logging.basicConfig(level=logging.INFO,format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',\ # datefmt='%c', filename='test.log') logging.debug('the debug...') logging.info('the info...') logging.warning('the warning...') logging.error('the error...') logging.critical('the critical...') # 对象的配置 # 先创建一个log对象 logger logger = logging.getLogger() logger.setLevel(logging.DEBUG) # 创建一个控制文件输出的操作文件符 fh = logging.FileHandler('my.log',encoding='utf-8') # 创建一个控制屏幕输出的屏幕操作符 sh = logging.StreamHandler() sh.setLevel(logging.WARNING) # 创建格式 fmt = logging.Formatter('%(asctime)s %(name)s[line:%(lineno)d] %(levelname)s %(message)s', datefmt='%Y-%m-%d %H:%M:%S') smt = logging.Formatter('%(asctime)s [line:%(lineno)d] %(levelname)s %(message)s') # 文件操作符绑定一个格式 fh.setFormatter(fmt) # 屏幕操作符绑定一个格式 sh.setFormatter(smt) # logger对象来绑定:文件操作符,屏幕操作符 logger.addHandler(fh) logger.addHandler(sh) logging.debug('the debug...') logging.info('用户信息...') logging.warning('the warning...') logging.error('the error') logging.critical('the critical...')
十、模块和包
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 在import模块发生了? ''' 1、寻找模块 2、如果找到了这个模块,就开辟一个空间,然后执行这个模块 3、把这个模块中的名字都收录到这个新开辟的空间中 4、创建一个变量来引用这个模块的空间 ''' ''' 1、模块不会重复被导入 2、模块与文件的内存空间始终是相互隔离的 3、模块的名字必须是符合变量的命名规范的 ''' # 模块的导入与修改 import time from my_module import * print(name) time.sleep(10) from my_module import * print(name) from importlib import reload import time import my_module print(my_module.name) time.sleep(10) reload(my_module) print(my_module.name) #pyc文件、pyi文件 #pyc只能提高程序的启动效率并不能提高程序的执行效率 #模块不能循环引用 import my_module print(dir(my_module)) #可以获取这个模块中所有的名字 __all__ 跟import *搭配 __all__['name','fun'] #导入包的两种方式 #绝对导入,相对导入 #单独导入包名称时不会导入包中所有包含的所有子模块
十一 、re模块
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#什么是正则表达式? 只和字符串打交道 #是一种规则 来约束字符串的规则 # 字符组 是元字符中的一个 # 在字符组中所有的字符都可以匹配任意一个字符位置上能出现的内容 # 如果在字符串中有任意一个字符是字符组中的内容,那么就是匹配上的项 # [0-9] # [a-z] # [A-Z] # ascii编码小的值 指向一个大的值 # [0-9a-zA-Z] # [1-9][0-9] # \d表示匹配一个数字 [0-9] # 元字符 # \w word \d digit \s space \n next \t tab \W \D \S # 元字符 # \w \d \s \W \D \S \n \t 匹配特殊的字符 # ^ $ \b # 匹配边界 # [] [^] # 字符组相关的 # | # 或 # () # 分组 # . # 匹配除了换行符之外的任意字符 # 写一个正则规则匹配一个手机号码 # 量词 # ?+ * {n} {n,} {n,m} # \d+整数 # \d+\.\d+ 小数 # \d+\.\d+|\d+ 整数或者小数 # \d+(\.\d+)? # 贪婪匹配 : 正则会尽量多的帮我们匹配 # 默认贪婪 回溯算法 # 非贪婪匹配 :会尽量少为我们匹配 # 量词?表示非贪婪 惰性匹配 # .*?x 表示匹配任意长度任意字符遇到一个x就立即停止 # 元字符 # 元字符 量词 # 元字符 量词 ? 在量词的范围内尽量少的匹配这个元字符 # 分组 对某些固定的内容做量词约束 # 或 把长的放前面 # 转义符 # pattern = r'\\n' # s = r'\n' import re ret=re.findall(r"\d+\.\d+|(\d+)","1-2*(60+(-40.35/5)-(-4*3))") print(ret) ret.remove('') print(ret) findall res = re.findall('\d+','ss12sd234') print(res) # 返回值 是一个列表 所有匹配到的项 res = re.search('\d+','ss12sd234') print(res) print(res.group()) # 返回值 : 返回一个SRE_Match对象 # 通过group去取值 # 且只包含第一个匹配到的值 # findall的特点 优先显示分组中的内容 ret = re.findall('www\.(?:baidu|taobao)\.(?:com)','www.baidu.com') print(ret) # search可以通过参数查看指定分组 ret = re.search('www\.(baidu|taobao)\.(com)','www.baidu.com') if ret: print(ret.group()) print(ret.group(1)) print(ret.group(2)) # match 同search 不过紧在字符串开始处匹配 ret = re.match('a','aac acd').group() print(ret) # split 先按a分割得到['','bcd'],再按b分割得到['','','cd'] ret = re.split('[ab]','abcd') print(ret) # sub 将数字替换成H,参数1表示只替换1次 ret = re.sub('\d','H','sa12ww12',1) print(ret) # subn 将数字替换成A,返回元祖(替换的结果,替换了多少次) ret = re.subn('\d','A','sa12ww12') print(ret) # compile 将正则表达式编译成一个正则表达式对象,再调用其方法 obj = re.compile('\d{3}') ret = obj.search('qwe123ew12') print(ret.group()) # finditer 返回一个存放结果的迭代器 res = re.finditer('\d','3ee12cd34') print(res) for i in res: print(i.group()) print(next(res).group()) print(next(res).group()) print([i.group() for i in res]) # split的优先级 #在匹配部分加上()之后所切出的结果是不同的, #没有()的没有保留所匹配的项,但是有()的却能够保留了匹配的项, res = re.split('\d+','wq1ew2we') res = re.split('(\d+)','wq1ew2we') print(res) # 匹配标签 res = re.search('<(?P<name>\w+)>\w+</(?P=name)>','<h1>hdhs</h1>') print(res.group('name')) print(res.group()) res = re.search(r'<(\w+)>\w+</\1>','<h1>hdhs</h1>') print(res.group(1))
十二、异常处理
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 异常处理 # 异常:在编译阶段没问题,在执行阶段才报错 # 语法错误:在程序执行之前就应该规避掉,不应该留到程序中进行异常处理 # 异常出现后,程序不会继续执行 try: print(name) except NameError: print('name is not defind') try: num = input('<<<') print(int(num)) except NameError: print('name is not defind') except ValueError: print('invalid literal') # Exception 可以捕获所有的异常 try: num = input('<<<') print(int(num)) except NameError: print('name is not defind') except Exception as e: print(e) # 没有异常,才执行else try: num = input('<<<') print(int(num)) except ValueError: print('name is not defind') else: print('执行成功') # trr else不支持这种写法,语法错误 try: print(1) else: print(2) # finall 无论如何都执行 try: print(name) finally: print('无论如何都执行') # 自定义异常 class DiyError(BaseException): def __init__(self,message): self.message = message def __str__(self): return self.message try: raise DiyError('类型错误') except DiyError as e: print(e) # 爬虫例子 import re import json from urllib.request import urlopen def getPage(url): html = urlopen(url) return html.read().decode('utf-8') def parsePage(s): '<div class="item">.*?<div class="pic">.*?<em .*?>(?P<id>\d+).*?<span class="title">(?P<title>.*?)</span>' '.*?<span class="rating_num" .*?>(?P<rating_num>.*?)</span>.*?<span>(?P<comment_num>.*?)评价</span>', re.S com = re.compile( '<div class="item">.*?<em .*?>(?P<id>\d+).*?<span class="title">(?P<title>.*?)</span>' '.*?<span class="rating_num" .*?>(?P<rating_num>.*?)</span>.*?<span>(?P<comment_num>.*?)评价</span>.*?' '<span class="inq">(?P<assess>.*?)</span>', re.S) ret = com.finditer(s) for i in ret: yield { 'id':i.group('id'), 'title':i.group('title'), 'rating_num':i.group('rating_num'), 'comment_num':i.group('comment_num'), 'assess':i.group('assess') } def main(num): url = 'https://movie.douban.com/top250?start=%s&filter=' % num reponse_html = getPage(url) ret = parsePage(reponse_html) # print(ret) f = open('move_info.txt','a',encoding='utf-8') for obj in ret: print(obj) # data = str(obj) data = json.dumps(obj,ensure_ascii=False) f.write(data+'\n') count = 0 for n in range(25): main(count) count += 25