模块(日志,xml,os,sys,正则等)

模块分为三种: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
-os.path.getatime(path) 返回path所指向的文件或者目录最后存取的时间
import os

print(os.path.getatime('/Users/chen/PycharmProjects/untitled1/day22/test/os_test.py'))
===>结果是:1620977617.1586921
-os.path.getmtime(path) 返回path所指向文件或者目录最后修改的时间
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匹配任何空白字符,相当于类[\t\n\r\f\v]

import re
s = re.findall("\s","qu o123")
print(s)======[' ']

\S匹配任何非空白字符,相当于类[^\t\n\r\f\v]

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)====>[' ']

\b匹配一个特殊字符边界,比如空格,#,&等

import re
s = re.findall("I\\b","hello I am LIST")
代码是先经过python解释器转换再传入re模块的 而单独的\b在python中是有特殊意义的所以传给re模块的时候python会先转换成特殊意义然后传给re,这样就不会传给re \b,
所以需要多加一个\使其变得没有意义,这样re 模块就能接收到\b
print(s)===>['I']

-------------------
import re
s = re.findall(r"I\b","hello I am LIST")=====其中r代表原字符。代码是先经过python解释器转换再传入re模块的,所以加上r传入的时候会直接传给re模块
print(s)===['I']
--------------------
import re
s = re.findall("o\\\\l","hello\lojih") python 解释器传给re模块是是o\\l 那么\\在re模块中就解析为普通的\,所以会匹配字符串中的o\l
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'}
    []


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


posted @ 2021-05-13 09:27  wode110  阅读(136)  评论(0编辑  收藏  举报