模块
1.什么是模块?
一个模块就是一个py文件。
模拟博客园系统作业,100000行代码. 不可能全部存在一个文件.
- 不易维护.
- 效率低.
分文件: 10个文件.每个文件有50个函数,有一写相同功能或者相似功能的函数.代码冗余,重复性.我们应该将这10个函数提取出来,放在一个文件中,随用随拿.
2.模块的优点
- 节省代码.
- 容易维护,组织结构更清晰.
一个模块就是一个py文件,这个模块存储很多相似的功能,相似的函数的集合体.
3.模块的分类:
- 内置模块,标准库.python解释器自带的,time,os,sys,等等.200多种.
- 第三方库(模块),各种大神写的一些模块,通过pip install....安装.6000种.
- 自己写的模块.自定义模块.
4.import
# import tbjx
# # 当我引用tbjx模块的时候,实际上将tbjx.py执行一遍,加载到内存.
# import tbjx
# import tbjx
# import tbjx
# import tbjx
# import tbjx
# 只是第一次引用时,将此模块加载到内存.
-
执行文件:02 模块import
-
被引用文件(模块): tbjx.py
-
第一次导入模块发生的三件事
import tbjx n = 1 # 引用模块发生三件事. ''' 1. 将tbjx.py文件加载到内存. 2. 在内存中创建一个以tbjx命名的名称空间. 3. 通过tbjx名称空间的名字.等方式引用此模块的名字(变量,函数名,类名等等). ''' # print(tbjx.name) # tbjx.read1() # tbjx.read2()
-
被导入模块有独立的名称空间
# 坑:通过tbjx.的方式引用此模块的名字时,一定一定是从此模块中寻找. # 通过import 引用模块 他有自己的独立名称空间,与当前执行文件没有关系. name = '李业' print(tbjx.name) def read1(): print('in 02 模块import') tbjx.read1()
-
为模块起别名
起别名:将一个比较长的模块名化简成简单的. # import tbjx as cb # ##1 书写方便. # import tbjx as tb # print(tb.name) # tb.read1() # ##2 简化代码. # content = input('>>>').strip() # if content == 'mysql': # import mysql_ # mysql_.sqlprase() # elif content == 'oracle': # import oracle_ # oracle_.sqlprase() # content = input('>>>').strip() # # if content == 'mysql': # import mysql_ as db # elif content == 'oracle': # import oracle_ as db # # db.sqlprase() # 统一化接口
-
导入多个模块
引入多个模块 # import time,os,sys # 不推荐. import time import os import sys # 易于阅读 易于编辑 易于搜索 易于维护。
5.from... import...
# from tbjx import name
# from tbjx import read1
# print(globals())
# 相当于从tbjx模块的全局空间中将name,read1变量与值的对应关系
# 复制到当前执行文件的全局名称空间中.
# print(name)#name是复制一份过来
# read1()#是复制了read1的函数内存地址
# 优点:使用起来方便了.
# 缺点:容易与当前执行文件产生覆盖效果.
-
from... import...的使用
#from 文件夹 impot 文件名 #可以用文件名.函数名进行操作 # 特殊情况:极值情况,工作中不会出现.(了解) # 因为如果你要是引用一些模块的变量,那么执行文件中就不应该出现同名变量.
-
from... import...与import对比
-
一行导入多个
# from tbjx import name # from tbjx import read1
-
from... import *
# from ... import * 尽量别单独用 # from tbjx import * # print(name) # read1() # read2() # 1,全部将tbjx的所有名字复制过来,无用功. # 2,容易覆盖. # from ... import * 与__all__配合使用(写在模块文件中)
6.py文件的两种功能
-
py文件的第一个功能:执行文件(承载代码) 脚本.
直接打印
__name__
返回__main__
-
py文件的第二个功能: 模块(被执行文件).
直接打印
__name__
返回tbjx
模块名
作用:用来控制.py文件在不同的应用场景下执行不同的逻辑(或者是在模块文件中测试代码)
7.模块的搜索路径
寻找模块的路径: 内存 ----> 内置模块 ---> sys.path中找
# 只要这三个地方:内存 内置模块 sys.path可以找到这个引用的模块的路径,这个模块就可以直接引用到.
# import sys
# # print(sys.path)
# # import tbjx
# print(sys.modules)
# 如何引用到tbjx1.py
import sys
# print(sys.path)
sys.path.append(r'D:\s23\day15')
# import tbjx
import tbjx1
tbjx1.read1()
序列化模块
序列化:将一个数据结构(list,dict....)转化成一个特殊的序列(特殊的字符串)的过程.
# l1 = [1, 2, 3]
# ret = str(l1)
# print(ret,type(ret))
# print(eval(ret)) # 不让用
# 文件存取时,遇到的矛盾.
# dic ={'username': '太白', 'password': 123}
# dic = {1: {'username': '太白', 'password': 123,'status': False},
# 2:{'username': 'alex', 'password': 123,'status': False}
# }
# 这个字典能放在全局么?
# with open('register.json',encoding='utf-8',mode='w') as f1:
# f1.write(str(dic))
# with open('register',encoding='utf-8') as f1:
# ret = f1.read()
# print(ret,type(ret))
#
# # 数据结构 --- > str() 存储在文件, 读取出来时,反转不回去.
# # 网络传输.
# l1 = [i for i in range(100000)]
# # 凡是数据通过网络传出去最终的格式必须bytes
# s1 = str(l1)
# b1 = s1.encode('utf-8')
# print(b1) # b1可以发送出去
#
# s2 = b1.decode('utf-8')
# print(s2,type(s2))
# s2 转化不成列表了.
# 我们现在要解决的问题: 如果有一种特殊的字符串,这个字符串可以与任何的数据结构互相转换.
序列化模块分类:
# 序列化模块: 将一中数据结构转化成特殊的序列(特殊的字符串,bytes)并且还可以反转回去.
# json模块: 是所有语言公认的一种序列.最最常用的
#所以支持的python数据结构有限: int str bool dict list(tuple),None,float
# None ---> Null ----> NUll
# dict --->
# pickle模块: 只能python语言中使用的,序列化模块:
# 支持python所有的数据类型以及对象.
# shevle模块(不讲): 课下了解(只能是文件存取).
json序列化:
两对四个方法:
dumps,loads 主要用于网络传输,可以用于文件的存取.
import json
# dumps,loads 主要用于网络传输,可以用于文件的存取.
# dic = {'username': '太白', 'password': 123,'status': False}
# ret = json.dumps(dic)
# # print(ret,type(ret))
# ret_dict = json.loads(ret)
# print(ret_dict)
# 特殊的参数
# dic = {'username': '太白', 'password': 123,'status': False}
# # print(dic)
# ret = json.dumps(dic,ensure_ascii=False,sort_keys=True)
# print(ret,type(ret))
# import json
# dic = {'username': '太白', 'password': 123,'status': False}
# s_dict = json.dumps(dic)
# with open('jsonlx.json',encoding='utf-8',mode='w') as f1:
# f1.write(s_dict)
#
# with open('jsonlx.json',encoding='utf-8') as f2:
# content = f2.read()
# print(json.loads(content))
多个数据如何存储到一个文件中?
import json
# dic1 = {'username': '太白', 'password': 123,'status': False}
# dic2 = {'username': 'alex', 'password': 123,'status': False}
# dic3 = {'username': 'ly', 'password': 123,'status': False}
# with open('jsonmore.json',encoding='utf-8',mode='a') as f1:
# f1.write(f'{json.dumps(dic1)}\n{json.dumps(dic2)}\n{json.dumps(dic3)}')
# with open('jsonmore.json',encoding='utf-8') as f1:
# for line in f1:
# ret = json.loads(line)
# print(ret,type(ret))
pickle序列化:python专用
pickle序列化:
dumps,loads 只能是网络传输
import pickle
# dumps,loads 只能是网络传输
# l1 = ['wusir', '太白', '小黑', 666]
# ret = pickle.dumps(l1)
# # print(ret)
#
# l2 = pickle.loads(ret)
# print(l2,type(l2))
dump load 数据结构存取文件.
import pickle
# l1 = ['wusir', '太白', '小黑', 666]
# with open('pickle练习.pickle',mode='wb') as f1:
# pickle.dump(l1,f1)
# with open('pickle练习.pickle', mode='rb') as f1:
# ret = pickle.load(f1)
# print(ret,type(ret))
# 多个数据写入文件
l1 = ['wusir', '太白', '小黑1', 666]
l2 = ['wusir', '太白', '小黑2', 666]
l3 = ['wusir', '太白', '小黑3', 666]
# with open('pickle练习1.pickle',mode='wb') as f1:
# # pickle.dump(l1,f1)
# # pickle.dump(l2,f1)
# # pickle.dump(l3,f1)
#
# with open('pickle练习1.pickle', mode='rb') as f1:
# ret1 = pickle.load(f1)
# ret2 = pickle.load(f1)
# ret3 = pickle.load(f1)
# print(ret1,ret2,ret3)
os模块
# 目录: 文件夹.
# 工作目录,当前目录,父级目录: day17
import os
# print(os.getcwd()) # D:\s23\day17 绝对路径 ***
# os.chdir(r'D:\s23\day9')
# print(os.getcwd())
# print(os.curdir)
# print(os.pardir)
# 和文件夹相关 ***
import os
# os.makedirs('dirname1/dirname2/dirname3/dirname4') # 多级目录
# os.removedirs('dirname1/dirname2/dirname3/dirname4') # 截止到有文件的那层
# os.mkdir(r'd:\abc') # 单级目录
# os.rmdir('abc')
# print(os.listdir(r'D:\s23\day15'))
#
# os.remove() 删除一个文件 ***
# os.rename("oldname","newname") 重命名文件/目录 ***
# print(os.stat(r'D:\s23\day17\01 昨日内容回顾.py'))
# path 和路径相关 ***
# print(os.path.abspath('04 os模块.py')) # D:\s23\day17\01 昨日内容回顾.py
# print(os.path.split(os.path.abspath('01 昨日内容回顾.py'))) # ('D:\\s23\\day17', '01 昨日内容回顾.py')
# print(os.path.dirname(r'D:\s23\day9\01 初始函数.py')) # 获取父级目录
# print(os.path.dirname(os.path.abspath('01 昨日内容回顾.py')))
# print(__file__) # 动态获取当前文件的绝对路径
# 获取当前文件的爷爷级的目录
# print(os.path.dirname(os.path.dirname(__file__)))
# print(os.path.basename(r'D:\s23\day9\01 初始函数.py')) # 获取文件名
# print(os.path.exists(r'D:\s23\day9\02 初始函数.py'))
# 判断是否是绝对路径
# print(os.path.isabs(r'D:\s23\day9\01 初始函数.py'))
# print(os.path.isabs(r'day17/01 昨日内容回顾.py'))
# 判断该路径是否是一个文件路径
# print(os.path.isfile(r'D:\s23\day9\01 初始函数.py'))
# print(os.path.isfile(r'D:\s23\day9'))
# print(os.path.isdir(r'D:\s23\day17\dirname1\dirname2'))
# print(os.path.exists(r'D:\s23\day17\dirname1\dirname2'))
# 判断是否是一个目录(文件夹)
# print(os.path.isdir(r'D:\s23\day17\02 序列化模块.py'))
# D:\s23\day16\评论文章
# path = os.path.join('D:','s23','day20','随便')
# print(path)
# par_dir = os.path.dirname(__file__)
# print(par_dir) # D:/s23/day17
# path = r'D:\s23\day17\db\lydata'
# path = par_dir + '\db' +'\lydata'
# path = os.path.join(par_dir,'db','lydata')
# with open(path,encoding='utf-8',mode='a') as f1:
# f1.write('李业在红浪漫消费998元')
# print(os.path.getatime('D:\s23\day17\db\lydata'))
# print(os.path.getmtime('D:\s23\day17\db\lydata'))
# print(os.path.getsize('D:\s23\day17\db\lydata'))
# print(os.stat(r'D:\s23\day17\01 昨日内容回顾.py'))
sys模块
import sys
# sys.path ***
# print(sys.version) # 版本
# for i in range(3):
# print(i)
# # exit() # 强制退出
# # quit()
# for i in range(5):
# print(i)
# print(sys.platform)
hashlib模块
加密模块, 摘要算法,散列算法,等等.它是一堆加密算法的集合.
liye|zmdsb
太白|123
明文形式存储的,带来安全隐患.
hashlib如何加密?
- 将一个bytes类型的数据 通过hashlib进行加密返回 一个等长度的16进制数字.
- 过程不可逆.
- 相同的bytes类型的数据通过相同的加密方法得到的数字绝对相同.
- 不相同的bytes类型的数据通过相同的加密方法得到的数字绝对不相同.
撞库: 111111, 123456, 000000,19980123,
{'202cb962ac59075b964b07152d234b70': 123456}
hashlib 的用途:
- 密码加密.
- 文件一致性校验.
密码加密:
# 密码加密
# md5
# ret = hashlib.md5()
# ret.update('123'.encode('utf-8'))
# s = ret.hexdigest()
# print(s,type(s))
# 撞库
# ret = hashlib.md5()
# ret.update('123456*@qwe'.encode('utf-8'))
# s = ret.hexdigest()
# print(s,type(s))
# 加固定盐
# ret = hashlib.md5('xxx教育'.encode('utf-8'))
# ret.update('123456'.encode('utf-8'))
# s = ret.hexdigest()
# print(s,type(s))
# 加动态的盐
# username = input('输入用户名:').strip()
# password = input('输入密码').strip()
# ret = hashlib.md5(username[::2].encode('utf-8'))
# ret.update(password.encode('utf-8'))
# s = ret.hexdigest()
# print(s)
# sha系列: 安全系数高,耗时高.
# 加盐,加动态盐
# ret = hashlib.sha512()
# ret.update('123456fdklsajflsdfjsdlkafjafkl'.encode('utf-8'))
# s = ret.hexdigest()
# print(s,type(s))
#
文件的一致性校验:
# low版
# import hashlib
# ret = hashlib.md5()
# with open('MD5文件校验',mode='rb') as f1:
# content = f1.read()
# ret.update(content)
# print(ret.hexdigest())
#
# 分步update
# s1 = '老男孩教育 最好的python 讲师 是 太白'
#
# ret = hashlib.md5()
# ret.update('老男孩教育'.encode('utf-8'))
# ret.update(' 最好的python'.encode('utf-8'))
# ret.update(' 讲师 是'.encode('utf-8'))
# ret.update(' 太白'.encode('utf-8'))
# print(ret.hexdigest()) # 90c56d265a363292ec70c7074798c913
# 高达上版,也可以用for
import hashlib
def md5_file(path):
ret = hashlib.md5()
with open(path,mode='rb') as f1:
while 1:
content = f1.read(1024)
if content:
ret.update(content)
else:
return ret.hexdigest()
print(md5_file(r'D:\s23\day17\python-3.7.4rc1-embed-win32.zip'))
规范开发
conf文件夹:
settings.py:
配置文件,就是放置一些项目中需要的静态参数,比如文件路径,数据库配置,软件的默认设置等等
lib文件夹:
common.py:
公共组件文件,这里面放置一些我们常用的公共组件函数,并不是我们核心逻辑的函数,而更像是服务于整个程序中的公用的插件,程序中需要即调用。比如我们程序中的装饰器auth,有些函数是需要这个装饰器认证的,但是有一些是不需要这个装饰器认证的,它既是何处需要何处调用即可。比如还有密码加密功能,序列化功能,日志功能等这些功能都可以放在这里。
core文件夹:
src.py:
这个文件主要存放的就是核心逻辑功能,你看你需要进行选择的这些核心功能函数,都应该放在这个文件中。
bin文件夹:
start.py:
项目启动文件。你的项目需要有专门的文件启动,而不是在你的核心逻辑部分进行启动的
db文件夹
register:
这个文件文件名不固定,register只是我们项目中用到的注册表,但是这种文件就是存储数据的文件,类似于文本数据库,那么我们一些项目中的数据有的是从数据库中获取的,有些数据就是这种文本数据库中获取的,总之,你的项目中有时会遇到将一些数据存储在文件中,与程序交互的情况,所以我们要单独设置这样的文件。
log文件夹:
access.log
log文件顾名思义就是存储log日志的文件。日志我们一会就会讲到,日志主要是供开发人员使用。比如你项目中出现一些bug问题,比如开发人员对服务器做的一些操作都会记录到日志中,以便开发者浏览,查询。
README
说明文件
time模块
与时间相关的模块:
三种形式:
-
时间戳(timestamp) :通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。我们运行“type(time.time())”,返回的是float类型
-
人类看得懂的时间,格式化时间. 2019-6-28 12:00
-
结构化时间: python语言使用的,解释器使用的
元组(struct_time) :struct_time元组共有9个元素共九个元素:(年,月,日,时,分,秒,一年中第几周,一年中第几天等)
# print(time.time())当前的时间戳
# 格式化时间:
# 字符串类型
# print(time.strftime("%Y-%m-%d %H:%M:%S"))
# print(time.strftime("%y-%m-%d %H:%M:%S %A"))
# ret = time.strftime("%Y{}%m{}%d{} %H:%M:%S")
# print(ret)
# print(ret.format('年','月','日'))
#结构化时间
# print(time.localtime())
# 时间戳 转化成 格式化时间
# timestamp = time.time()当前时间戳
# st = time.localtime(timestamp)时间戳转结构化时间
# # print(st)
# ft = time.strftime("%y-%m-%d %H:%M:%S",st)结构化时间转格式化时间
# print(ft)
# 格式化时间转化成时间戳
# ft = time.strftime("%y-%m-%d %H:%M:%S")当前格式化的时间
# # print(ft)
# st = time.strptime(ft,"%y-%m-%d %H:%M:%S")格式化时间转结构化时间
# # print(st)
# timestamp = time.mktime(st)结构化时间转时间戳
# print(timestamp)
random模块
import random
# print(random.random()) # 大于0且小于1之间的小数
# print(random.uniform(1, 6)) # ***
# print(random.randint(1,5)) # 1 5 可以取到 ***
# print(random.randrange(1,10,2)) # 顾头不顾尾 ***
# print(random.choice(['如花', '凤姐', '石榴姐', 1])) # ***
# print(random.sample(('如花', '凤姐', '石榴姐'), 3)) # 可以控制元素个数 ***
# 打乱顺序
# item = [i for i in range(10)]
# random.shuffle(item)
# print(item)
datatime模块
import datetime
# from datetime import datetime
# time_now = datetime.datetime.now()
# print(str(time_now), type(time_now))
#
# print(datetime.datetime.now() + datetime.timedelta(weeks=3))三周后
# print(datetime.datetime.now() + datetime.timedelta(weeks=-4))四周前
# print(datetime.datetime.now() + datetime.timedelta(days=-15))15天前
# current_time = datetime.datetime.now()
# print(current_time.replace(year=1979))1979年的现在
# print(current_time.replace(year=1989,month=4,day=25))1989年四月25日的这个时间
# print(datetime.date.fromtimestamp(4332543543))这个时间戳的格式化时间
包的使用
# 创建一个包,也会发生三件事:
1. 将该aaa包内 __init__py文件加载到内存.
2. 创建一个以aaa命名的名称空间.
3. 通过aaa. 的方式引用__init__的所有的名字.
time模块 一个py文件,200个函数,功能特别多,分文件,分三个文件,time文件夹: time1 time2 time3py文件,这个time文件夹就叫做包.
1. import
2. from ... import ...
3. 相对导入与绝对导入
-
# from ... import ... # 通过这种方式不用设置__init__文件 # from aaa import m1 # m1.func() # from aaa.bbb.m2 import func1 # func1() # from aaa.bbb import m2 # m2.func1() # from a.b.c import d #.e.f # c的. 的前面一定是包 # import 的后面一定是名字,并且不能 再有点
logging 日志
工作日志分四个大类:
-
系统日志:记录服务器的一些重要信息:监控系统,cpu温度,网卡流量,重要的硬件的一些指标,运维人员经常使用的,运维人员,记录操作的一些指令.
-
网站日志: 访问异常,卡顿,网站一些板块,受欢迎程度,访问量,点击率.等等,蜘蛛爬取次数等等.
-
辅助开发日志: 开发人员在开发项目中,利用日志进行排错,排除一些避免不了的错误(记录),辅助开发.
-
记录用户信息日志: 用户的消费习惯,新闻偏好,等等.(数据库解决)
日志: 是谁使用的? 一般都是开发者使用的.
三个版本:
-
Low版(简易版).
import logging logging.basicConfig( # level=logging.DEBUG level=10, format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s', # filename=r'test.log',写入文件文件名 ) logging.debug("调试") logging.info("正常") logging.warning("警告") logging.error("报错") logging.critical("严重跑路")
-
标配版(标准版)
import logging #创建一个logging对象 logger=logging.getLogger() #创建一个文件对象 fh=logging.FileHandler('标配版.log',encoding='utf-8') #创建一个屏幕对象 sh=logging.StreamHandler() #配置显示格式 formatter1=logging.Formatter('%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s') formatter2=logging.Formatter('%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s') fh.setFormatter(formatter1) sh.setFormatter(formatter2) logger.addHandler(fh) logger.addHandler(sh) #总开关 logger.setLevel(10) fh.setLevel(10) sh.setLevel(10) logging.debug("调试") logging.info("正常") logging.warning("警告") logging.error("报错") logging.critical("严重跑路")
-
旗舰版(项目中使用的,Django项目) ***
- 自定制(通过字典的方式)日志
- 轮转日志的功能.
import logging.config # 定义三种日志输出格式 开始 standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \ '[%(levelname)s][%(message)s]' #其中name为getlogger指定的名字 simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s' id_simple_format = '[%(levelname)s][%(asctime)s] %(message)s' # 定义日志输出格式 结束 logfile_name = 'login.log' # log文件名 logfile_path_staff = r'D:\s23\day19\日志模块\旗舰版日志文件夹\staff.log' logfile_path_boss = r'D:\s23\day19\日志模块\旗舰版日志文件夹\boss.log' # log配置字典 # LOGGING_DIC第一层的所有的键不能改变 LOGGING_DIC = { 'version': 1, # 版本号 'disable_existing_loggers': False, # 固定写法 'formatters': { 'standard': { 'format': standard_format }, 'simple': { 'format': simple_format }, 'id_simple':{ 'format': id_simple_format } }, 'filters': {}, 'handlers': { #打印到终端的日志 'sh': { 'level': 'DEBUG', 'class': 'logging.StreamHandler', # 打印到屏幕 'formatter': 'id_simple' }, #打印到文件的日志,收集info及以上的日志 'fh': { 'level': 'DEBUG', 'class': 'logging.handlers.RotatingFileHandler', # 保存到文件 'formatter': 'standard', 'filename': logfile_path_staff, # 日志文件 'maxBytes': 5000, # 日志大小 5M 'backupCount': 5, 'encoding': 'utf-8', # 日志文件的编码,再也不用担心中文log乱码了 }, 'boss': { 'level': 'DEBUG', 'class': 'logging.handlers.RotatingFileHandler', # 保存到文件 'formatter': 'id_simple', 'filename': logfile_path_boss, # 日志文件 'maxBytes': 5000, # 日志大小 5M 'backupCount': 5, 'encoding': 'utf-8', # 日志文件的编码,再也不用担心中文log乱码了 }, }, 'loggers': { #logging.getLogger(__name__)拿到的logger配置 '': { 'handlers': ['sh', 'fh', 'boss'], # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕 'level': 'DEBUG', 'propagate': True, # 向上(更高level的logger)传递 }, }, } def md_logger(): logging.config.dictConfig(LOGGING_DIC) # 导入上面定义的logging配置 logger = logging.getLogger() # 生成一个log实例 return logger # logger.debug('It works!') # 记录该文件的运行状态 dic = { 'username': '小黑' } def login(): # print('登陆成功') md_logger().info(f"{dic['username']}登陆成功") # # def aricle(): # print('欢迎访问文章页面') login() # aricle()
re模块(正则)
import re
# re.findall()
# 正则表达式: 从一大堆字符串中,找出你想要的字符串.
# 在于对你想要得这个字符串进行一个精确地描述.
# s1 = 'fdsa太白金星'
# print(s1.find('白'))
# 单个字符匹配
# \W与\w
# \w 数字字母下划线中文
# \W 非数字字母下划线中文
# print(re.findall('\w', '太白jx 12*() _'))
# print(re.findall('\W', '太白jx 12*() _'))
# \s 匹配的 空格 \t \n
# \S 匹配的 非空格 \t \n
# print(re.findall('\s','太白barry*(_ \t \n'))
# print(re.findall('\S','太白barry*(_ \t \n'))
# \d 匹配所有的数字
# \D 非匹配所有的数字
# print(re.findall('\d\d','1234567890 alex *(_'))
# print(re.findall('\D','1234567890 alex *(_'))
# \A ^从开头开始匹配
# print(re.findall('\Ahello','hello hello 太白 hell'))
# print(re.findall('^hello','hello hello 太白 hell'))
# \Z,从结尾开始匹配
# \z,有一点问题
# $从结尾开始匹配
# print(re.findall('fjkdsla太白金星\Z','fjkdsla太白金星'))
# print(re.findall('金星$','fjkdsla太白金星'))
# \n \t
# print(re.findall('\n','fdsak\n fkjdlas\n \t'))
# print(re.findall('\t','fdsak\n fkjdlas\n \t'))
# 元字符匹配
# . ? * + {m,n} .* .*?
# . 匹配任意一个字符
# 如果匹配成功光标则移到匹配成功的最后的字符
# 如果匹配未成功光标则向下移动一位再次匹配
# print(re.findall('a.b','aaabbb'))
# ? 匹配0个或者1个由左边字符定义的片段。
# print(re.findall('a?b', 'ab aab'))
# print(re.findall('a?b', 'sb ab aabb'))
#* 匹配0个或者多个左边字符表达式。 满足贪婪匹配
# print(re.findall('a*b','aaab ab b'))
# # print(re.findall('a*b','aasab ab b'))
# + 匹配1个或者多个左边字符表达式。 满足贪婪匹配
# print(re.findall('a+b','aaab ab b'))
# {m,n} 匹配m个至n(n能取到)个左边字符表达式。 满足贪婪匹配
# print(re.findall('a{1,5}b', 'ab aab aaab aaaab aaaaaab aaaaabb'))
# .* 贪婪匹配 从头到尾.
# print(re.findall('a.*b','aab abbliye aaab abbb aa#b'))
# print(re.findall('a.*b','asb abbliyeaaab \nabbb aa#y',re.DOTALL)) # a...................b
# .*? 此时的?不是对左边的字符进行0次或者1次的匹配,
# 而只是针对.*这种贪婪匹配的模式进行一种限定:告知他要遵从非贪婪匹配 推荐使用!
# 0个或者多个
# print(re.findall('a.*?b','ab a#bbbbbb aaab'))
# print(re.findall('a.*b','a#bbbbbb'))
# print(re.findall('a.*?b','a#bbbbbb'))
# []
# print(re.findall('a[abc]b', 'aab abb acb adb afb a_b'))
# print(re.findall('a[abc][bd]b', 'aabb aaabc abd acdbb'))
# print(re.findall('a[0-9]b', 'a1b a3b aeb a*b arb a_b'))
# print(re.findall('a[a-z]b', 'a1b a3b aeb a*b arb a_b'))
# print(re.findall('a[A-Z]b', 'aAb a3b aEb a*b aRb a_b'))
# print(re.findall('a[a-zA-Z]b', 'aab a3b aAb a*b aTb a_b'))
# 当你想匹配 - 时,要把它放在[]里面的最前面或者最后面
# print(re.findall('a[-*$]b', 'a-b a$b a)b a*b '))
# ^ 在中括号里面最前面代表取反
# print(re.findall('a[0-9]b', 'a1b a$b a5b a*b '))
# print(re.findall('a[*^)]b', 'a^b a$b a5b a*b '))
# 'alex_sb wusir_sb ritian_sb 太白_nb yuanbao_sb'
s = 'alex_sb wusir_sb ritian_sb 太白_nb yuanbao_sb dsb_sb'
# print(re.findall('\w+_sb',s))
# # 'alex_sb wusir_sb ritian_sb 太白_nb yuanbao_sb'
# # ()
# print(re.findall('(\w+)_sb',s))
# |
# print(re.findall('alex|太白|wusir', 'alex太白wusiraleeeex太太白odlb'))
# # () 分组里面加了?: 将全部的内容给我返回回来,而不是将组内的内容返回
# print(re.findall('companies|company',
# 'Too many companies have gone bankrupt, and the next one is my company')) # ['ies', 'y']
# printy companies have gone bankrupt, and the next one is my company'))(re.findall('compan(?:ies|y)',
# # 'Too man
# search match
import re
# 找到第一个符合条件的字符串就返回,返回一个对象,通过对象.group()
# ret = re.search('sb|alex', 'alex sb sb barry 日天')
# ret = re.search('alex', 'fdsjkfd fjdsklalex gfdlgjfdlgjfggfjlgjfkdl')
# # # print(ret)
# # # print(ret.group())
#
# # 从字符串开头匹配,如果以符合条件的字符串开头则返回,否则返回None
# ret = re.match('alex', 'alexfdskfd fjdsklalex gfdlgjfdlgjfggfjlgjfkdl')
# print(ret)
# print(ret.group())
# split
# s1 = 'alex;wusir,太白 吴超~宝元'
# import re
# print(re.split('[;, ~]',s1))
import re
# print(re.sub('barry', '太白', 'barry是最好的讲师,barry就是一个普通老师,请不要将barry当男神对待。'))
# obj = re.compile('\d{2}')
# # print(obj.search('fdsa12fds435454').group())
# print(obj.findall('fjdskalf2134fkjsd3245fdjsl545'))
# finditer
ret = re.finditer('\d','54fjdkls4535lsdfj6776')
# print(ret)
# print(next(ret))
# print(next(ret).group())
# print(next(ret).group())
# for i in ret:
# print(i.group())
# print(list(ret))
s1 = '''
时间就是f4321995-04-27,2005-04-27
1999-04-27 老男孩教育创始人
老男孩老师 alex 1980-04-27:1980-04-27
2018-12-08
'''
# print(re.findall('\d{4}-\d{2}-\d{2}',s1))
#
# 匹配一个qq账号 10000开始 第一个元素规定就是非零数字,后面的是随意的数字长度大于5位.
s2 = '56546326546757'
print(re.findall('[1-9][0-9]{4,}',s2))