模块分为三种:1,python标准库(内置模块)。 2,第三方模块 3,应用程序自定义模块
-自定义模块
import
用import时会先把文件中的命令都执行一边,然后执行需要执行的函数命令。
-执行对应文件
-引入变量名
-import 运行时只能找到当前操作执行文件所在目录
例如:在同一个目录(同级目录)下新建一个test.py 和cal.py文件 cal.py内容如下,需要在test.py文件中引入cal.py函数并运用
def add(x,y):
return x+y
def sub(x,y):
return x-y
代码如下:
-代码1:
import cal
print(cal.add(5,3))======>结果是:8
print(cal.sub(5,3))======》结果是:2
-代码2:
from cal import add,sub
print(add(5,3))=====》结果是:8
print(sub(5,3))=====〉结果是:2
例如:*在不同目录下新建一个test.py 和cal.py文件 cal.py内容如下,需要在test.py文件中引入cal.py函数并运用
test.py文件在 day21 lessons文件下而cal.py在 day21 lessons-new-cal.py
def add(x,y):
return x+y
def sub(x,y):
return x-y
代码是:
from new import cal
print(cal.add(5,3))====>结果是8
*不同目录下 例如:new 目录下有2个包(web1, my_module) new--web1--test.py new--my_module-cal.py-功能
现在想在test.py中调用cal.py中的一个功能
import sys,os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
#代码中的os.path.abdpath(__file__) 代表当前文件的绝对路径
#代码中的os.path.dirname()代表上一级路径
sys.path.append(BASE_DIR)
from my_module import cal
if __name__=='__main__':
print(cal.add(3,5))===》结果是8
*********************************************
目录 new包下有一个执行文件test.py 以及一个web1 包(web1-web2-web3-cal.py) ,需要在test.py 中运行web3包中的cal.py文件
cal.py 文件内容是:
def add(x,y):
print(x+y)
代码如下:
-代码1
from web1.web2.web3 import cal
cal.add(3,5)===》结果是8
-代码2
from web1.web2.web3.cal import add
add(3,5)====结果是8
不可用代码:
from web1.web2 import web3=====》此代码相当于执行web3 包中的_init_.py
web3.cal.add() 代码会报错
if __name__ == '__main__' :下边写的执行代码是对上边所写代码进行测试。若别的文件引用此代码所在的文件中的功能,—__name__ 等于sys.path的执行结果,所以下边代码不会运行
if __name__ == '__main__':
main run======>此代码代表程序
-python标准库模块
1,time 模块
-time.sleep() 延迟时间
-时间戳 time.time() :做计算
import time
print(time.time())====>1620632052.788367. 代表从1970年到现在一共多少秒
-结构化时间:
time.localtime()--当地时间
print(time.localtime())=====>time.struct_time(tm_year=2021, tm_mon=5, tm_mday=10, tm_hour=15, tm_min=38, tm_sec=23, tm_wday=0, tm_yday=130, tm_isdst=0)
t=time.localtime()
print(t.tm_year)====>结果是:2021 代码意思是:打印年份
time.gmtime()---世界标准时间
print(time.gmtime())====time.struct_time(tm_year=2021, tm_mon=5, tm_mday=10, tm_hour=7, tm_min=47, tm_sec=49, tm_wday=0, tm_yday=130, tm_isdst=0)
-将结构化时间转换成时间戳 time.mktime()
print(time.mktime(time.localtime()))=====>1620633262.0
- 将结构化时间转换为格式化的字符串时间 代码:time.strftime(x,t) x代表格式化的字符串时间 ,t 默认 time.localtime()
%Y代表年。
%m代表月
%d代表日
%X代表时分秒
print(time.strftime('%Y-%m-%d %X'))====>2021-05-10 16:01:28
- 将格式化的字符串时间 转换成 结构化时间代码:time.strptime()
print(time.strptime('2012:5:10:12:30:05','%Y:%m:%d:%X'))==>time.struct_time(tm_year=2012, tm_mon=5, tm_mday=10, tm_hour=12, tm_min=30, tm_sec=5, tm_wday=3, tm_yday=131, tm_isdst=-1)
-asctime 是将结构化时间转换为字符串时间 有固定格式
import time
print(time.asctime())===>Mon May 10 16:19:14 2021
-ctime 是将时间戳转化为字符串时间 有固定格式
import time
print(time.ctime())====>Mon May 10 16:19:14 2021
-datetime
import datetime
print(datetime.datetime.now())=====>2021-05-10 16:23:25.260349
2,random 模块 随机模块
-random.random() 0-1范围内 浮点类型
import random
print(random.random())====0.9317954898962848
-random.ranint(1,3) #[1,3] 整型 范围是大于等于1,小于等于3整数
print(random.randint(1,3))==结构是1-3内随机数字
-random.randrange(1,3) #[1,3) 范围是:大于等于1,小于3的整数
print(random.randrange(1,3))
-random.choice() 随机选取其中一个元素
print(random.choice([11,22,33]))===》结果是随机出现列表中随机元素
-random.sample(x,y) x代表可迭代对象,y 代表一次出现几个元素
import random
print(random.sample([11,22,33],1))==》[22] 出现一个元素
import random
print(random.sample([11,22,33],2))===》[11,33]出现2个元素
-random.uniform() 任意范围内的浮点型
import random
print(random.uniform(1,3))====此代码是表示随机取1-3范围内的浮点型
-random.shuffle() 改变可迭代对象元素顺序
import random
ret = [1,2,5,6]
random.shuffle(ret)
print(ret)===》[5, 1, 2, 6]
随机验证码 代码如下:
import random
def v_code():
ret = ''
for i in range(5):=====此处代表范围是0,1,2,3,4 即[0,5)
num = random.randint(0,9)
alf = chr(random.randint(65,122))
s =str(random.choice([num,alf]))
ret += s
return ret
print(v_code())====》结果是个5位数的随机码
临时修改系统环境变量,代码如下:
import sys
sys.path.append()
3,sys 模块
-sys.exit(n) 退出程序,正常退出时exit(
0
)
-sys.version 获取Python解释程序的版本信息
-sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.path.append('自定义模块路径') #将自定义的模块路径加入环境变量中
-sys.platform 返回操作系统平台名称
-sys.argv 命令行参数
List
,第一个元素是程序本身路径
-sys.stdout 输出相关
sys.stdout.write() 输出()
sys.stdout.flush() 动态输出
sys.stdout.write('#')====》结果是#
例如:进度条代码:
import sys,time
for i in range(20):
sys.stdout.write('#')
time.sleep(0.2)
sys.stdout.flush()====>结果是进度条式动态输出#
*4,json &pickle 模块
json可以进行任何语言的交换,
- json 用于【字符串】和 【python基本数据类型】 间进行转换
- json.dumps()/json.dump() 将python基本数据类型转换成json字符串类型
- json.loads() /json.load() 将json字符串转换成python基本数据类型
- 只要符合json规范,就可以直接用json.loads()=====json规范是带有双引号的字符串元素
json.dumps
将 Python 对象编码成 JSON 字符串json.loads
将已编码的 JSON 字符串解码为 Python 对象
import json
c = {'hello':'alisa'}===={“hello”:“alisa”}=====》“{“hello”:“alisa”}”
p = json.dumps(c)
print(p,type(p))===>{"hello": "alisa"} <class 'str'>. 元素最后变成双引号 ==>已经转换成字符串了
i= 8
p = json.dumps(i)
print(p,type(p))===>8 <class 'str'>
例如:创建新文件new_file,将字典c 写入新文件new_file 中,代码如下:
import json
c = {"hello":"alisa"}
方式一:
f = open("new_file","w")
c_str = json.dumps(c)====第一步
f.write(c_str)=====第二步。====================》这两步相当于代码 json.dump(c,f)
f.close
方式二:
f = open("new_file","w")
json.dump(c,f)
f.close()
将写入后的new_file 文件,中的字典c再次提取出来代码如下:
方式一:
f_read = open("new_file","r")
data = json.loads(f_read.read())==第一步
print(data,type(data))=====第二步。 =============》这两部相当于 json.load(f)
方式二:
f_read = open("new_file","r")
data =json.load(f_read)
print(data,type(data)
------------pickle---------
pickle 与json 用法一样,pickle 是转化为字节。json是转换为json字符串
一般用json.
5,os 模块
-os.getcwd 直接获取当前工作目录
import os
print(os.getcwd())=====>结果是:/Users/chen/PycharmProjects/学习/com/wang
-os.chdir()改变当前目录. os.chdir(.) 当前目录
-os.chdir(‘..‘) 返回上一层
-os.makedirs('dirname1/dirname2')可生成多层递归目录
-os.mkdir(‘dirname’)生成单级目录
-removedirs('dirname1') 若目录为空,则删除并递归到上一层目录,如若也为空则删除
-os.rmdir('dirname') 删除单级目录,若目录不为空则无法删除,报错
-os.listdir() 列出指定目录下所有的子目录和文件 包括隐藏文件。并以列表方式打印出来
-os.remove() 删除一个文件
-os.rename('oldname','newname') 重命名文件名
-os.stat('文件名') 获取文件/目录信息
import os
print(os.stat('sss.py'))
结果是:
os.stat_result(st_mode=33188, st_ino=9553040, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=60, st_atime=1620872591, st_mtime=1620872590, st_ctime=1620872590)
st_atime=====>上次访问时间 st_mtime=====》上次修改时间 st_ctime====〉创建时间。uid===用户名。gid===组数。 size===文件字节数
-os.sep 输出操作系统特定的路径分隔符,windows 下为‘\',linux 下为'/'
-os.path.split(path) 将path分割成目录和文件名二元组返回
import os
print(os.path.split(r'/Users/chen/PycharmProjects/untitled1/day22/test/os_test.py'))==结果如下:
('/Users/chen/PycharmProjects/untitled1/day22/test', 'os_test.py')
-os.path.dirname(path) 返回path的上一层目录。其实就是os.path.split(path)的第一个元素
print(os.path.dirname(r'/Users/chen/PycharmProjects/untitled1/day22/test/os_test.py'))===结果如下:
/Users/chen/PycharmProjects/untitled1/day22/test
-os.path.basename(path) 返回path最后的文件名。如何path以/或结尾,那么就会返回空值。即os.path.split(path)的第二个元素
print(os.path.basename(r'/Users/chen/PycharmProjects/untitled1/day22/test/os_test.py'))=====结果如下:
os_test.py
-os.path.abspath(path) 返回path规范化的绝对路径,当前工作的绝对路径
-os.path.exists(path) 如果path存在,返回
True
;如果path不存在,返回
False
-os.path.isabs(path) 如果path是绝对路径,返回
True
-os.path.isfile(path) 如果path是一个存在的文件,返回
True
。否则返回
False
-os.path.isdir(path) 如果path是一个存在的目录,则返回
True
。否则返回
False
-os.path.join(path1[, path2[, ...]]) 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
-os.path.getatime(path) 返回path所指向的文件或者目录的最后存取时间
-os.path.getmtime(path) 返回path所指向的文件或者目录的最后修改时间
-os.path.join(path1,path2) 路径拼接
import os
a = '/Users/chen/PycharmProjects/untitled1'
b = 'day22/test/os_test.py'
print(os.path.join(a,b))====>/Users/chen/PycharmProjects/untitled1/day22/test/os_test.py
import os
a = os.path.dirname(os.path.abspath('path'))
# print(os.path.abspath('path'))
b = 'b.txt'
c = 'c.txt'
print(os.path.join(a,b,c))#结果是:/Users/chen/PycharmProjects/untitled1/day23/b.txt/c.txt
import os
print(os.path.getatime('/Users/chen/PycharmProjects/untitled1/day22/test/os_test.py'))
===>结果是:1620977617.1586921
import os
print(os.path.getmtime('/Users/chen/PycharmProjects/untitled1/day22/test/os_test.py'))
===》结果是:1620977617.1005054
6,xml 模块
import xml.etree.ElementTree as ET #当引入模块名字太长时可以自己将模块名字命名为一个简单的名字 例如:ET
tree = ET.parse('xml_lesson') #解析文件 相当于python 中文件的read 方法
root = tree.getroot() #获取文件的根
print(root.tag) #相当于打印根(标签)的名字 tag是标签的意思
#遍历xml文件所有内容代码: attrib 是属性的意思(=后边内容是属性) x.attrib 代表x的属性 x.text 是获取xml中文本的意思
for i in root:
print(i.tag) #第一层根的标签名 ===结果如下:
# country
# country
# country
print(i.attrib) #第一层的属性 形式例如:country name="Liechtenstein" 中的"Liechtenstein"是属性 ==》结果如下:
# {'name': 'Liechtenstein'}
# {'name': 'Singapore'}
# {'name': 'Panama'}
print(i.text) #获取第一层的文本中包裹的内容 例如:<gdppc>141100</gdppc> 中的141100 是文本内容
#没有结果,因为这一层的根没有text
for j in i:
print(j.tag)===结果如下:
# rank
# year
# gdppc
# neighbor
# neighbor
#......等第二层所有的标签名
print(j.attrib)====结果如下:
# {'updated': 'yes'}
# {'updated': 'yes'}
# {}
# {'direction': 'E', 'name': 'Austria'}
# {'direction': 'W', 'name': 'Switzerland'}
#.....等第二层所有的属性
print(j.text)=====结果如下:
# 2
# 2010
# 141100
# None
# None
#...等第二层所有的text
#只遍历year节点
for item in root.iter('year'):
print(item.tag,item.text)
#修改xml文件
import xml.etree.ElementTree as ET
tree = ET.parse('xml_lesson')
root = tree.getroot()
for node in root.iter('year'):
new_year =int(node.text) + 1
node.text = str(new_year)
node.set("updated","yes") #====>set("属性名","属性值") 增加属性
tree.write("new_lesson.xml")#=====》将更新后的xml内容写入文件中代码是 tree.write("文件名")
#删除rank>50的城市
import xml.etree.ElementTree as ET
tree = ET.parse('xml_lesson')
root = tree.getroot()
for country in root.findall("country"): #=====寻找xml中所有的标签 代码 x.findall('标签名') findall 可以查找多个
rank = int(country.find("rank").text) #====find 只能查找一个
if rank > 50:
root.remove(country)#删除
tree.write("remove_lesson.xml")
创建xml
例如:创建test.xml文档,文档内容是:
根:namelist
子根目录名:name
name子根目录下包含:name ,age,sex
name属性,
import xml.etree.ElementTree as ET
new_xml = ET.Element('namelist')#创建根目录名字是namelist
name = ET.SubElement(new_xml,"name",attrib={"enrolled":"yes"})#==创建子根标签名字是name,属性是'enrolled':'yes'
age = ET.SubElement(name,"age",attrib={"checked":"no"})#====创建name 下边的子根标签名字是age,属性是‘checked':'no"
sex = ET.SubElement(name,"nex")#==创建name下的子根标签名字是sex
sex.text = '33'#==sex子根标签的文本内容是33
et = ET.ElementTree(new_xml)#生成文档对象固定格式,必须写此代码
et.write("test.xml",encoding = 'utf8',xml_declaration = True)此代码是固定格式必须写
打印生成的格式代码是:ET.dump(new_xml)
* 7 logging 模块 日志模块
日志级别默认WARNING
级别等级(从低到高):NOTESET < DEBUG < INFO < WARNING < ERROR < CRITICAL
默认的日志格式是:日志级别,Logger 名称,用户输出信息
import logging
logging.basicConfig(
level=logging.DEBUG,
)
#固定格式如下:其中括号内容可以自己添加
logging.debug("hello")
logging.info('who')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical message')
结果如下:DEBUG:root:hello
INFO:root:who
WARNING:root:warning message
ERROR:root:error message
CRITICAL:root:critical message
----------------------------------------------------------
-logging设置参数格式
import logging
#给logging设置参数,将打印内容存在文档logger.log文件中;若是不存打印结果会直接显示在屏幕上
# filemode 是设置日志的模式例如: filemode = 'w'代表可写模式,若不设置模式,日志默认追加
#format='%(设置内容)s'。format = 设置日志打印内容
logging.basicConfig(
level=logging.DEBUG,
filename='logger.log',
filemode='w',
format='%(asctime)s %(filename)s [%(lineno)d] %(message)s %(levelname)s'
)
#固定格式如下:其中括号内容可以自己添加
logging.debug("hello")
logging.info('who')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical message')
logging.basicConfig函数各参数:
filename: 指定日志文件名
filemode: 和file函数意义相同,指定日志文件的打开模式,'w'或'a'
format: 指定输出的格式和内容,format可以输出很多有用信息,如上例所示:
%(name)s Logger的名字
%(levelno)s: 数字形式的日志级别
%(levelname)s: 文本形式的日志级别
%(pathname)s: 调用日志输出函数的模块的完整路径名,可能没有,其实就是sys.argv[0]
%(filename)s: 调用日志输出函数的模块的文件名
%(module)s:调用日志输出函数的模块名
%(funcName)s: 调用日志输出函数的函数名
%(lineno)d: 打印日志输出的函数语句所在代码行
%(created)f 当前时间,用UNIX标准的表示时间的浮点数表示
%(relativeCreated)d 输出日志信息的时间,自Logger创建以来的毫秒数
%(asctime)s: 字符串形式的当前时间 默认格式“2003-07-08 16:49:45,896”逗号后边的是毫秒
%(thread)d: 打印线程ID
%(threadName)s: 打印线程名称
%(process)d: 打印进程ID
%(message)s: 用户输出信息
datefmt: 指定时间格式,同time.strftime()
level: 设置日志级别,默认为logging.WARNING
stream: 指定将日志的输出流,可以指定输出到sys.stderr,sys.stdout或者文件,默认输出到sys.stderr,当stream和filename同时指定时,stream被忽略 意思是只能屏幕/文件显示,不能一起显示
*********************************************
灵活运用logger 方法,代码如下:
import logging
logger = logging.getLogger() #logger获得logging的方法
fh = logging.FileHandler("new_log") #代表日志向文档new_log输出,其中new_log可以自己改变,放入想放入的文档名
ch = logging.StreamHandler() #代表日志向屏幕输出
fm = logging.Formatter('%(asctime)s %(message)s') #设置日志输出格式
fh.setFormatter(fm) #fh 获得fm设置的日志格式
ch.setFormatter(fm) #ch 获得fm设置的日志格式
logger.addHandler(fh) # logger获得将日志向文档输出的方法fh
logger.addHandler(ch) #logger获得将日志向屏幕输出的方法ch
logger.setLevel('DEBUG')#将logger 级别设置成debug 若不设置级别,默认级别是warning
#以下是级别设置
logger.debug('debug')
logger.info('info')
logger.warning('warning message')
logger.error('error message')
logger.critical('critical')
最后将其写入函数,方便下次直接调用代码如下:
def logger():
import logging
logger = logging.getLogger() #logger获得logging的方法
fh = logging.FileHandler("new_log") #代表日志向文档new_log输出,其中new_log可以自己改变,放入想放入的文档名
ch = logging.StreamHandler() #代表日志向屏幕输出
fm = logging.Formatter('%(asctime)s %(message)s') #设置日志输出格式
fh.setFormatter(fm) #fh 获得fm设置的日志格式
ch.setFormatter(fm) #ch 获得fm设置的日志格式
logger.addHandler(fh) # logger获得将日志向文档输出的方法fh
logger.addHandler(ch) #logger获得将日志向屏幕输出的方法ch
logger.setLevel('DEBUG')#将logger 级别设置成debug
logger.debug('debug')
logger.info('info')
logger.warning('warning message')
logger.error('error message')
logger.critical('critical')
return logger
注意:只要父根输出一次,子根就会跟着输出一次
练习实例:日志创建一个根logger ,然后根logger 下创建一个子根son_logger,son_logger的级别设置是DEBUG,根logger 和子根的日志输出方向都是文档father_log和屏幕,最后的结果输出的结果是?
import logging
logger = logging.getLogger()
logger1 = logging.getLogger('son_logger')#创建子根son_logger
logger1.setLevel(logging.DEBUG)#设置子根的级别
hf = logging.FileHandler('father_log')
cf = logging.StreamHandler()
gf = logging.Formatter('%(asctime)s %(message)s %(levelname)s')
hf.setFormatter(gf)
cf.setFormatter(gf)
logger.addHandler(hf)
logger.addHandler(cf)
logger1.addHandler(hf)
logger1.addHandler(cf)
logger.debug('debug')
logger.info('info')
logger.warning('warning message')
logger.error('error message')
logger.critical('critical')
logger1.debug('debug 1')
logger1.info('info 1')
logger1.warning('warning message 1')
logger1.error('error message 1')
logger1.critical('critical 1')
结果是:根输出3条日志记录,字根输出10条日制记录。
因为:根logger 不设置,默认级别是warning,因此从warning开始往下输出总共3条;
子根设置的级别是DEBUG,只要父根logger输出一次,字根就输出1次,所以字根总共输出2次,一次5条,总共输出10条记录
2021-05-19 11:14:15,230 warning message WARNING
2021-05-19 11:14:15,230 error message ERROR
2021-05-19 11:14:15,230 critical CRITICAL
2021-05-19 11:14:15,230 debug 1 DEBUG
2021-05-19 11:14:15,230 debug 1 DEBUG
2021-05-19 11:14:15,230 info 1 INFO
2021-05-19 11:14:15,230 info 1 INFO
2021-05-19 11:14:15,231 warning message 1 WARNING
2021-05-19 11:14:15,231 warning message 1 WARNING
2021-05-19 11:14:15,231 error message 1 ERROR
2021-05-19 11:14:15,231 error message 1 ERROR
2021-05-19 11:14:15,232 critical 1 CRITICAL
2021-05-19 11:14:15,232 critical 1 CRITICAL
*8 re 模块 正则
正则表达式被编译成一系列的字节码,然后用c编写的匹配引擎执行
字符匹配(普通字符,元字符)
-普通字符 大多数字符和字母都会和自身匹配 ==》(完全匹配)
import re
s = re.findall("alex",'123adkjihalexllo')
print(s)====>结果是:['alex']
-元字符:. ^ $ * + ? { } [ ] | ( ) ======》(模糊匹配)
- . 通配符。(可代表除换行符以外的任意符号) 一个.通常代表一个字符
例如:找以a开头以x结尾的字符串
import re
s = re.findall("a..x","ajidhiudhalexlle")
print(s)===》['alex'] 字符串中a和x之间有2个字符,所以有2个.会有结果
------------------------------------
import re
s = re.findall("a.x","ajidhiudhalexlle")
print(s)====》[]
- ^ 代表从字符串的最开头匹配。能匹配上就成功,匹配不上结果为空
import re
s = re.findall("^a..d","ajidhiudhaledlle")===>代表匹配字符串最开头的4个字符,看能否匹配上
print(s)===》['ajid']
-------------------------------------------------
import re
s = re.findall("^a..x","ajidhiudhaledlle")
print(s)
-$代表从字符串的最末尾开始匹配,能匹配上就成功,匹配不上结果为空
import re
s = re.findall("d..e$","ajidhiudhaledlle")===>代表匹配字符串最后4个字符,是不是以d开头以e结尾
print(s)===>['dlle']
-------------------------------------------------------
import re
s = re.findall("d..e$","ajidhiudhaledlle$")
print(s)===>[] 因为$并不是普通字符,是元字符所以匹配不上。
- |代表 或 例如 ab|cd 代表 ab 或者 cd
import re
s = re.findall("ab|cd","ajdubab|hic") ====>代表匹配 ab 或者 cd
print(s)
-重复符号
1, * 代表:重复 *之前紧挨着的字符 重复:0次到无穷次 贪婪匹配
import re
s = re.findall("alex*","ajidhiale")
print(s)=====>['ale'] 因为*可以匹配0次x 所以结果是ale
---------------------------
import re
s = re.findall("alex*","ajidhialexxx")
print(s)====>['alexxx']
2,+ 代表:重复+之前紧挨着的字符 重复:1到无穷次 贪婪匹配
import re
s = re.findall("alex+","ajidhiale")
print(s)===>[] 因为+是从1次开始匹配的,没有匹配上所以结果为空
-------------
import re
s = re.findall("alex*","ajidhialexxx")
print(s)====>['alexxx']
3,? 代表:重复?之前紧挨着的字符 重复0到1次。贪婪匹配
import re
s = re.findall("alex?","ajidhialexxx")
print(s)===>['alex'] 因为 ? 是重复0到1次
4, { } 代表重复{ }之前紧挨着的字符, 重复几次可以自己定义 贪婪匹配。例如:
-- 0到无穷次 {0,} == *
-- 1到无穷次 {1,} == +
-- 0到1次 {0,1} == ?
--重复6次 {6}
import re
s = re.findall("alex{6}","ajidhialexxx")
print(s)===>[]因为x 重复6次,匹配不上
--------------
import re
s = re.findall("alex{0,1}","ajidhialexxx")
print(s)====>['alex']
将贪婪匹配变成惰性匹配(最少匹配):在重复符号后边加上 ? 就可以
import re
s = re.findall("alex*","ajidhialexxx")
print(s)======》['alexxx']
变成惰性匹配代码如下:
import re
s = re.findall("alex*?","ajidhialexxx")
print(s)======>结果是:['ale']
-元字符之字符集
1, 字符集:[ ]
-在字符集中没有意义的符号,只看作普通的字符:例如: *
- [ ] 中内容是或的关系,匹配是任意选其中一个字符。
import re
s = re.findall("a[j*l]","ajidhiala*xxx") [j*l]中的 *就是普通的字符。[]中内容看作3个字符并且任何一个字符之间都是或的关系
print(s)=====>['aj', 'al', 'a*']
-在字符集中有意义的符号:- ^
- 代表范围即从x到 x
import re
s = re.findall("a[0-9]","a5huia8kha9"). 其中[0-9]代表>=0 <=9的所有数字
print(s)===>['a5', 'a8', 'a9']
--------------------------
import re
s = re.findall("q[a-z]*","quonibjf") [a-z]*代表字符集[a-z]重复0到无穷次
print(s)=====》结果是['quonibjf']
^ 在字符集中,代表非(不是) 的意思
import re
s = re.findall("q[^a-z]","q896uonibjf"). ====^在字符集中是非的意思,所以是:只要不是a-z的字符都可以匹配
print(s)===》q8
---------------
import re
s = re.findall("q[^a-z]","quo")
print(s)====结果是[]
-元字符之转义符
后边跟元字符 代表:去除特殊意义 例如 *
后跟普通字符实现特殊意义。例如:d
d 匹配任何十进制数,相当于类[0,9]
import re
s = re.findall("d","quo123")
print(s)===>['1', '2', '3']
D匹配任何非十进制数,相当于类[^0,9]
import re
s = re.findall("D","quo123")
print(s)=====['q', 'u', 'o']
s匹配任何空白字符,相当于类[ fv]
import re
s = re.findall("s","qu o123")
print(s)======[' ']
S匹配任何非空白字符,相当于类[^ fv]
import re
s = re.findall("S","qu o123")
print(s)========['q', 'u', 'o', '1', '2', '3']
w匹配任何字母数字字符以及_,相当于类[a-zA-z0-9_]
import re
s = re.findall("w","quo123_")
print(s)=====>['q', 'u', 'o', '1', '2', '3', '_']
W匹配任何非字母数字字符,相当于类[^a-zA-z0-9_]
import re
s = re.findall("W","qu o123_")
print(s)====>[' ']
匹配一个特殊字符边界,比如空格,#,&等
import re
s = re.findall("I\b","hello I am LIST")
代码是先经过python解释器转换再传入re模块的 而单独的在python中是有特殊意义的所以传给re模块的时候python会先转换成特殊意义然后传给re,这样就不会传给re ,
所以需要多加一个使其变得没有意义,这样re 模块就能接收到
print(s)===>['I']
-------------------
import re
s = re.findall(r"I","hello I am LIST")=====其中r代表原字符。代码是先经过python解释器转换再传入re模块的,所以加上r传入的时候会直接传给re模块
print(s)===['I']
--------------------
import re
s = re.findall("o\\l","hellolojih") python 解释器传给re模块是是o\l 那么\在re模块中就解析为普通的\,所以会匹配字符串中的ol
print(s)====>['o\l']
-元字符之分组:() , search('?P< 组名>匹配目标')
import re
s = re.findall("abc+","abcccc")
print(s)===>['abcccc']
------------
import re
s = re.findall("(abc)+","abcccc")=======把abd 当作一个整体
print(s)===>['abc']
- search('?P< 组名>匹配目标') serch()匹配到第一个就会结束匹配
固定格式是:search('?P< 组名>匹配目标')
import re
s = re.search("(?P<name>[a-z]+)(?P<age>d+)","alisa12tom34alex89")
t = s.group("name","age")====》代表name 组的内容 和 age 组的内容
print(s)=====><re.Match object; span=(0, 7), match='alisa12'> ===这是匹配情况
print(t)===>('alisa', '12')
以上代码整合如下:
import re
s = re.search("(?P<name>[a-z]+)(?P<age>d+)","alisa12tom34alex89").group()
print(s)===>alisa12
************
import re
s = re.search("(?P<name>[a-z]+)(?P<age>d+)","alisa12tom34alex89").group("name")
print(s)====alisa
注意:findall() 中的匹配规则如果进行分组会优先匹配分组内容,一旦匹配上只会显示匹配的分组内容
若不需要优先,则需在分组内容最开始加上?: 以去除优先。如下:
import re
s=re.findall('www.(baidu|163).com','hhioowww.baidu.com')
print(s)===> ['baidu']
s1=re.findall('www.(?:baidu|163).com','hhioowww.baidu.com')
print(s1)===> ['www.baidu.com']
import re
s= '12+(34*6+2-5*(2-1)+(4*4+4))' 先匹配最里边括号里的
t = re.findall('([^()]+)',s)
print(t)====>['(2-1)', '(4*4+4)']
import re
s= re.findall('(abc)+','abcabcabc')
print(s)====>['abc'} 因为findall 优先匹配括号内内容,所以结果是abc
s= re.findall('(?:abc)+','abcabcabc')
print(s)=====>['abcabcabc']
re 模块下常用方法
- re.findall() 返回所有匹配条件的结果,放在列表里
import re
s = re.findall("ab",'abhgabc')
print(s)===>['ab', 'ab']
-re.search() 函数会在字符串内查找匹配格式,只找到第一个匹配就返回一个包,不在往后进行匹配
通过调用group方法返回匹配的字符串,如果字符串没有匹配则返回None
import re
s = re.search("ab",'abhgabc').group()
print(s)===>ab
import re
s = re.search("de",'abhgabc')
print(s)====None
-re.match() 同search 方法,只是相当于search(^) (即从字符串最开头开始匹配) 注意:match 也是只要匹配到就不在往后匹配
import re
s = re.match("hg",'abhgabc')
print(s)===>None 因为字符串最开头是ab 所有匹配不上
----------------------------------
import re
s = re.match("ab",'abhgabc').group()
print(s)=====ab
-re.split(' 按照此处内容分割','字符串')
import re
s = re.split("ab",'abc') 此处是按照ab 进行分割,所以ab 是 空 ,还剩个c 结果是:['', 'c']
print(s)==》['', 'c']
---------------------
import re
s = re.split("a|b",'abc')
首先按照a 进行分割结果是['',bc]==然后把结果按照b分割,结果是['', '', 'c']
print(s)===》['', '', 'c']
-re.sub(‘查找目标’,‘替换成什么’,‘字符串’,匹配次数) 替换
import re
s = re.sub("a",'A','abc')===将字符串中的a替换成A
print(s)===>Abc
import re
s = re.sub("d+",'A','a2c123a2',2) 代表将字符串中数字替换成A ,数字2代表只匹配2次
print(s)====>aAcAa2
-re.subn(‘查找目标’,‘替换成什么’,‘字符串’) 替换字符串中字符,并告知替换几次
import re
s = re.subn("d+",'A','a2c123a2')
print(s)====》('aAcAaA', 3)其中3是表示替换了几次的意思
-re.compile('匹配规则')。编辑匹配规则然后调用进行匹配(可调用多次)
import re
obj= re.compile("d+") #编辑匹配规则
s = obj.findall('jg34di23gfbi')
print(s)===》['34','23']
-re.finditer() 返回迭代器。
import re
s=re.finditer("d",'kdg12ihu56uj')
print(s)==》<callable_iterator object at 0x7f843a680588> #返回迭代器
print(next(s))=====》<re.Match object; span=(3, 4), match='1'> #调用迭代器,返回组
print(next(s).group())==》2=========== 有几个结果需要调用几次,调用一次循环一次,出现一个结果
print(next(s).group())===〉5
9, configparser模块: 配置文件的解析模块
-对象:针对配置文件操作
-创建配置文件
import configparser
config = configparser.ConfigParser() #相当于一个空字典,此代码必须写上
config['DEFULT'] = {'ServerAliveInterval':45,
'Compression':'yes',
'CompressionLevel':'9',
'ForwardX11':'yes'} # 添加配置参数
config['bitbucket.org'] = {} #创建一个新的空字典bitbucket.org
config['bitbucket.org'] = {'User':'hg'} #添加配置参数
#或者代码:config['bitbucket.org']['User'] = 'hg'
config['topsecret.server.com'] = {}
config['topsecret.server.com'] = {'Port':'50022', 'ForwardX11':'no'}
with open('example.ini','w') as f:
config.write(f) #将所有的字典写入example.ini配置文件中
创建的example.ini文件内容如下:
[DEFULT]
serveraliveinterval = 45
compression = yes
compressionlevel = 9
forwardx11 = yes
[bitbucket.org]
user = hg
[topsecret.server.com]
port = 50022
forwardx11 = no
-配置文件的增,删,改,查
-查
注意:DEFAULT 比较特殊,一旦配置文件中有它,不论遍历哪个,都会输出DEFAULT下内容
import configparser
config = configparser.ConfigParser()
config.read("example.ini")
print(config.sections()) #===结果:['DEFULT', 'bitbucket.org', 'topsecret.server.com']
print('bytebong.com'in config) #===结果:False 判断查找内容(bytebong.com)是否在config 中
print(config['bitbucket.org']['user']) #===结果:hg
for i in config['bitbucket.org']: #====遍历 config['bitbucket.org']
print(i)====》结果如下: 因为配置文件中有DEFAULT ,DEFAULT 比较特殊,如果配置文件中命名了它,不论遍历那个文件都会出现它的内容
user
serveraliveinterval
compression
compressionlevel
forwardx1
print(config.options('bitbucket.org')) #相当于遍历bitbucket.org键
#结果是:['user', 'serveraliveinterval', 'compression', 'compressionlevel', 'forwardx11']
print(config.items('bitbucket.org'))#相当于取键值对
#结果是:[('serveraliveinterval', '45'), ('compression', 'yes'), ('compressionlevel', '9'), ('forwardx11', 'yes'), ('user', 'hg')]
print(config.get('bitbucket.org','CompressionLevel')) #取值
#结果是:9 在'bitbucket.org'下查找'CompressionLevel',没找到,但是因为有DEFAULT会在它下找,找到了,所以是9
-增加
import configparser
config = configparser.ConfigParser()
config.read("example.ini")
config.add_section('add') #增加add块
config.set('add','key1','value1') #给add块增加键值对
config.write(open('i.cfg','w'))#改后内容添加到文件中,不需关闭
-删除
import configparser
config = configparser.ConfigParser()
config.read("example.ini")
config.remove_section('topsecret.server.com')# 删除块topsecret.server.com
config.remove_option('bitbucket.org','user') #删除bitbucket.org下的键值对
config.write(open('i.cfg','w'))#改后内容添加到文件中,不需关闭
10,hashlib 模块:摘要算法
功能:用于加密的相关操作
主要提供算法有:md5 ,sha256,sha224,sha384,sha512,sha1
-md5算法
import hashlib
#注意:md5只能加密不能解密。用户登陆时只能设置把用户输入内容转换为秘文然后进行秘文比较
obj = hashlib.md5('在此可加上自己设置的字符串'.encode('utf-8'))#md5算法是将明文变成密文
#在括号内加上内容是"加严" 以变更保密,安全
obj.update('hello'.encode('utf-8'))#将字符串'hello'变成字节,编码是'utf-8'
print(obj.hexdigest())# 5d41402abc4b2a76b9719d911017c592 将不定长度字符串变成定长的密文
obj.update('hi'.encode('utf-8'))
print(obj.hexdigest()) #结果是:c2bbe4b78214a2568c3bfcb27981ab8a====>注意此结果是对‘hellohi'进行加密的结果
不想在原先字符串后边加上新字符串 再进行加密的需要重新命名 例如:obj = hashlib.md5() 中obj 需重新命名
-sha256算法
用法:同上md5 算法 但sha256最常用
11, optparse 模块
功能:对命令行解析命令
import optparse
class ArgvHandler():
def __init__(self):
self.op=optparse.OptionParser()
self.op.add_option('-s','--server',dest='server') #此处自定义-s代表ip地址
self.op.add_option('-P','--port',dest='port')#此处自定义-p代表端口
options,args=self.op.parse_args()
options.server = '192.168.1.4'#设置IP
options.port = '8080'#设置端口
print(options) #option结果是一个对象结果是:{'server': '192.168.1.4', 'port': '8080'}
print(args)#args 放入没有设置绑定的其他信息
ArgvHandler()
结果如下:{'server': '192.168.1.4', 'port': '8080'}
[]