• 模块(日志,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匹配任何空白字符,相当于类[ 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'}
        []


    
    
  • 相关阅读:
    Oracle传统基本体系结构初步介绍(4) 老猫
    oracle 嵌套表 老猫
    Oracle传统基本体系结构初步介绍(2) 老猫
    Oracle传统基本体系结构初步介绍(3) 老猫
    Oracle分析函数参考手册三 老猫
    Oracle传统基本体系结构初步介绍(1) 老猫
    Oracle临时表用法的经验心得 老猫
    博客美化&typora写博客攻略(博客园版) WHU
    探索式测试随笔 wing
    接口测试随笔 wing
  • 原文地址:https://www.cnblogs.com/wode110/p/14763180.html
Copyright © 2020-2023  润新知