Python全栈day21-22-23(模块)

一,python的模块node

  Python 模块(Module),是一个 Python 文件,以 .py 结尾,包含了 Python 对象定义和Python语句。python

  模块让你可以有逻辑地组织你的 Python 代码段。linux

  把相关的代码分配到一个模块里能让你的代码更好用,更易懂。web

  模块能定义函数,类和变量,模块里也能包含可执行的代码正则表达式

  模块一共有三种算法

    •   python标准库  (例如time)
    •   第三方模块  (安装后和标准库同样调用)
    •   应用程序自定义模块 

 

新建一个python包,名称为day21_lesson和文件夹不一样的是包里面包含__init__.py文件shell

  新建两个py文件 test.py和cal.py编程

   cal.pyjson

def add(x,y):
    return x + y

def sub(x,y):
    return x - y

  test.pyapp

import cal

print(cal.add(5,3))

8

  PS:调用须要在前面加模块名在家对应定义的函数名

    使用Pycharm调用cal时候会标红,可是执行不会报错

 

  import操做

  1,执行对应文件(假如里面有print会先打印出对应内容 只是实际不会这样去操做)

  2,引入变量 (函数也是一个变量)

  

  若是不想加模块名调用函数

#import cal
from cal import add
from cal import sub

print(add(5,3))
print(sub(5,3))

8
2

  若是有多个则使用* (不推荐这样调用,由于逻辑函数里面也可能会定义函数可能会重名,若是遇到重复的会按照顺序那个定义在最后就是那个有效)

#import cal
from cal import *


print(add(5,3))
print(sub(5,3))

8
2

  PS:使用from cal import sub这种调入方式仍是会执行cal.py里面全部的代码,而后把对应的变量调用过来

 

  调用模块首先从调用模块的执行文件路径下面找模块,其次从默认的路径找模块

  使用sys.path能够调出使用默认模块的路径,第一个就是执行文件的本地路径

import sys
print(sys.path)

['D:\\blzfmima\\python3_s3\\day21\\day21_lesson',
 'D:\\blzfmima\\python3_s3',
 'D:\\blzfmima\\python3_s3\\venv\\Scripts\\python35.zip',
 'D:\\blzfmima\\python3_s3\\venv\\DLLs',
 'D:\\blzfmima\\python3_s3\\venv\\lib',
 'D:\\blzfmima\\python3_s3\\venv\\Scripts',
 'C:\\Python35\\Lib',
 'C:\\Python35\\DLLs',
 'D:\\blzfmima\\python3_s3\\venv',
 'D:\\blzfmima\\python3_s3\\venv\\lib\\site-packages',
 'C:\\Program Files\\JetBrains\\PyCharm 2017.3.1\\helpers\\pycharm_matplotlib_backend']

  在执行文件test.py在新建一个python包 把对应的模块文件放入里面

  

  调用的方式不同 从my_module里面调用cal

from my_module import cal

print(cal.add(1,3))

  是从执行文件的路径下面开始寻找调用的模块,假如文件路径是这样

  

  bin.py是程序入口文件

from my_module import main

main.run()

  main.py是主程序文件(虽然main.py和调用的模块cal是同一文件夹下面可是这里不能使用import cal调用,由于本次的程序入口文件是bin.py因此这里main调用也必须从该入口文件开始)

#import cal

from my_module import cal def run(): print(cal.add(5,3))

  PS:若是必定想要使用import调用能够经过append方法把cal的路径添加到sys.path

 

  多层引用模块使用.来分割

from web.web1.web2 import  cal
print(cal.add(5,3))

8

  

  PS:import调用的是py文件 若是调用文件夹运行不会报错会执行对应的的包下面的__init__.py文件

    假如在__init__.py文件写入语句import . cal 也能够执行 ,不建议这样使用

 

  变量__name__ 在执行文件里面__name__的值为 __main__  在调用文件里面打印的是调用函数的路径,若是在cal里面加入print(__name__)使用其余的文件调用出现的值为web.web1.web2.cal

  使用if __name__=='__main__'进行判断的做用

  1,放在被调用的文件里面用于测试

   2,放在执行文件里面不想被其余文件调用

  

二,python内置模块

  1,time时间模块

  time.py

import time

#时间戳 (用于计算)
print(time.time()) #1516937562.8488374秒从1970年1月1日0时0分0秒开始算起的时间秒

#结构化时间  使用localtime取到一个时间对象,能够经过时间对象取值
print(time.localtime())
#time.struct_time(tm_year=2018, tm_mon=1, tm_mday=26, tm_hour=11, tm_min=46, tm_sec=4, tm_wday=4, tm_yday=26, tm_isdst=0)
t = time.localtime()
#根据时间对象取年及星期的第几天,星期一是0 打印为4表明星期五
print(t.tm_year)
print(t.tm_wday)
#----
#和localtime同样可是tm_hours少了8个小时是和格林尼治时间的对比,是世界标准时间
print(time.gmtime())
#time.struct_time(tm_year=2018, tm_mon=1, tm_mday=26, tm_hour=3, tm_min=46, tm_sec=4, tm_wday=4, tm_yday=26, tm_isdst=0)

#字符串时间
#把时间戳转换成结构化时间struct_time
print(time.localtime(1431242343))
#time.struct_time(tm_year=2015, tm_mon=5, tm_mday=10, tm_hour=15, tm_min=19, tm_sec=3, tm_wday=6, tm_yday=130, tm_isdst=0)

#将结构化时间转换成时间戳
print(time.mktime(time.localtime()))
#1516946698.0

#把结构化时间转换成字符串的时间 %X代指时分秒
print(time.strftime('%Y-%m-%d %X',time.localtime()))
#2018-01-26

#把字符串是时间装换成结构化时间(须要严格一一对应包括之间的空格及-符号,不然报错)
print(time.strptime('2018-01-26 14:13:32','%Y-%m-%d %X'))
#time.struct_time(tm_year=2018, tm_mon=1, tm_mday=26, tm_hour=14, tm_min=13, tm_sec=32, tm_wday=4, tm_yday=26, tm_isdst=-1)


#asctime把一个时间元祖或者struct_time表示为固定的字符串时间格式,若是没有传递参数默认传递time.localtime()
print(time.asctime())
#Fri Jan 26 14:34:10 2018
#把一个时间戳转换成time.asctime()的形式,若是没有传递参数默认使用time.time()
print(time.ctime())
#Fri Jan 26 14:34:10 2018

#time.sleep()推迟运行时间参数为秒
time.sleep(1)

#另一个时间模块datatime 打印的时间更加符合咱们需求
import datetime

print(datetime.datetime.now())

  关于时间模块的转换图示

 

 

  2,random模块

  随机模块.py 

  尾部付一个生成带字母和数字的字符串

import random

#生成一个0-1之间的随机浮点数
ret = random.random()
print(ret)
#0.06990352689202717

#生成一个区间的整数1,2,3
print(random.randint(1,3)) #[1,3]

#生成一个区间的整数不取最右边的1,2
print(random.randrange(1,3)) #[1,3)

#从一个可迭代对象里面随机选取一个元素
print(random.choice([11,22,33])) #[11,22,33]

#从一个可迭代对象里面随机选取几个元素 选两个生成一个列表
print(random.sample([11,22,33],2))

#生成一个范围内发浮点型
print(random.uniform(1,3))

#随机打乱顺序(不经常使用)
item = [1,2,3,4,5]
#打乱顺序修改原表,没有返回值
random.shuffle(item)
print(item)
#[4, 1, 2, 5, 3] 也多是其余的顺序

#写一个验证码函数

def v_code():
    #定义一个字符串接收验证码
    ret = ''
    for i in range(4):
        #生成一个随机数字
        num = random.randint(0,9)
        #生成两个随机字母 alf1是随机大写字母 alf2是随机小写字母
        alf1 = chr(random.randint(65,90))
        alf2 = chr(random.randint(97,122))
        #从两个随机字母中挑选一个
        alf = random.choice([alf1,alf2])
        #从数字或者字母中随机挑选一个
        s = str(random.choice([num,alf]))
        #拼接而后做为返回值返回
        ret += s
    return ret


res = v_code()
print(res)

  

   2,os模块

  os_test.py

import os

#getcwd获取当前工做目录
print(os.getcwd())
#D:\blzfmima\python3_s3\day22

#chdir改变工做目录至关于linux里面的cd
#能够是绝对路径也能够是当前目录的相对路径
#os.chdir('test1')
print(os.getcwd())
#D:\blzfmima\python3_s3\day22\test1

#curdir获取当前目录字符串名
print(os.curdir)
#.


#pardir获取当前目录的父目录字符串名
print(os.pardir)
#..

#makedirs生成多层递归目录新建两个文件夹其中dirname1和本文件同目录dirname2在dirname1的下一级目录
#至关于linux里面的mkdir -p命令
#os.makedirs('dirname1/dirname2')

#removedirs若目录为空则删除,并递归到上一级目录,若是也为空则删除,以此类推
#os.removedirs('dirname1/dirname2')

#mkdir生成单级目录至关于linux里面的mkdir
#os.mkdir('dirname')

#rmdir删除单级目录若是不为空则报错
#os.remove('dirname')

#listdir列出指定目录下面的全部文件和子目录,包括隐藏文件,并以列表的方式打印
#只列出一级目录
print(os.listdir())
#['dirname', 'os_test.py', 'test1']

#rename修改文件名
#os.rename('oldname','newname')

#stat列出对应文件的信息包括文件大小,建立时间修改时间等
print(os.stat('sss.py'))
#os.stat_result(st_mode=33206, st_ino=281474976879558, st_dev=1010701401, st_nlink=1, st_uid=0, st_gid=0, st_size=11, st_atime=1517191298, st_mtime=1517191298, st_ctime=1517191298)

#sep输出操做系统特定路径分隔符 win下为'\\' linux为'/'
print(os.sep)
# \

#linesep输出当前平台使用的行终止符 win下为'\r\n' linux下为'\n'
print(os.linesep)

#pathsep输出用于分割文件路径的字符串 win下为; linux下为:
print(os.pathsep)
# ;

#name输出字符串指示当前使用平台 win为'nt' linux为'posix'
print(os.name)
#nt

#system 运行shell命令直接显示
#os.system('ipcofig')

#split 将path分割成目录和文件名的二元组返回
print(os.path.split(r'D:/blzfmima/python3_s3/day21/day21_lesson/bin/bin.py'))
#('D:/blzfmima/python3_s3/day21/day21_lesson/bin', 'bin.py')

#dirname返回path目录,其实就是os.path.split(path)的第一个元素
print(os.path.dirname(r'D:/blzfmima/python3_s3/day21/day21_lesson/bin/bin.py'))
#D:/blzfmima/python3_s3/day21/day21_lesson/bin

#basename返回path最后的文件名若是以/或者\结尾那么会返回空值,及os.path.split(path)的第二个元素
print(os.path.basename(r'D:/blzfmima/python3_s3/day21/day21_lesson/bin/bin.py'))
#bin.py

#exists若是path存在返回True不然返回False
print(os.path.exists(r'D:/blzfmima/python3_s3/day21/day21_lesson/bin/bin.py'))
#True

#isabs若是是绝对路径返回True
print(os.path.isabs(r'D:/blzfmima/python3_s3/day21/day21_lesson/bin/bin.py'))
#True

#iffile是否是一个文件是文件返回True
print(os.path.isfile(r'D:/blzfmima/python3_s3/day21/day21_lesson/bin/bin.py'))
#True

#isdir是不是一个存在的目录返回True
print(os.path.isdir(r'D:/blzfmima/python3_s3/day21/day21_lesson/bin'))
#True

#join将多个路径组合后返回,第一个绝对路径以前的参数将被忽略
a = 'D:/blzfmima/python3_s3'
b = 'day21/day21_lesson/bin/bin.py'

print(os.path.join(a,b))
#D:/blzfmima/python3_s3\day21/day21_lesson/bin/bin.py

#getatime返回path所指向的文件或者目录的最后存取时间
print(os.path.getatime(r'D:/blzfmima/python3_s3/day21/day21_lesson/bin/bin.py'))
#getmtime返回path所指向的文件或者目录的最后修改时间
print(os.path.getmtime(r'D:/blzfmima/python3_s3/day21/day21_lesson/bin/bin.py'))


#environ获取系统环境变量
print(os.environ)

 

  3,sys模块

#print(sys.version)
#3.5.2rc1 (v3.5.2rc1:68feec6488b2+, Jun 12 2016, 08:56:24) [MSC v.1900 64 bit (AMD64)]

#path返回模块搜索路径
#print(sys.path)

#platform返回操做系统平台名称
#print(sys.platform)
#win32 或者linux

#stdout.write写进度条
import time
for i in range(10):

    sys.stdout.write("#")
    time.sleep(0.1)
    sys.stdout.flush()

  

  4,json模块

  以前咱们学习过用eval内置方法能够将一个字符串转换成python对象,不过,eval方法是有局限性的,对于普通的数据类型,json.loads和eval都能用,但遇到特殊类型的时间,eval就无论用了,因此eval的字典仍是一般用来执行一个字符串表达式,并返回表达式的值

  json_test.py

import json

dic = {'name':'zhangsan'}
dic_str = json.dumps(dic)
print(dic_str)
#{"name": "zhangsan"}
print(type(dic_str))
#<class 'str'>

#打开如下新文件把通过json.dumps转换后的字符串{"name": "zhangsan"}写入文件
with open('new_hello','w') as f_write:
    f_write.write(dic_str)

#以只读方式打开文件而且使用json.loads方法把字符串转换成对应的数据类型为dict
with open('new_hello','r') as f_read:
    data = json.loads(f_read.read())
    print(data)
    print(type(data))

{"name": "zhangsan"}
<class 'str'>
{'name': 'zhangsan'}
<class 'dict'>

  PS:字符串不必定须要先dumps以后才能loads字符串只要符合json规范便可loads

 

  5,pickle模块

  pickle_test.py

import pickle
dic = {'name':'zhangsan'}

j = pickle.dumps(dic)

#使用pickle序列化 生成的对象是不可直接读的,读取是乱码
#只能使用pickle反序列化
f = open('序列号对象_pickle','wb')
f.write(j)  #等价与pickle.dump(dic,f)
f.close()

#反序列化
f = open('序列号对象_pickle','rb')
data = pickle.loads(f.read())
f.close()

print(data['name'])

zhangsan

  PS:pickle可序列化的数据类型比json多,能够序列化函数,类。可是这种需求较少,通常直接使用json便可

 

  5,shelve模块(不经常使用了解便可)

   shelve模块比pickle模块简单,只有一个open函数,返回相似字典的对象,可读可写;key必须为字符串,而值是python所支持的数据类型

  shelve_test.py

import  shelve

#f = shelve.open(r'shelve1') #目的:将一根字典放入文本

#f['stu1_info'] = {'name':'zhangsan','age':18}
#f['stu2_info'] = {'name':'lisi','age':28}
#f['school_info'] = {'website':'edu.com','city':'shenzhen'}

#f.close()

f = shelve.open(r'shelve1')
print(f.get('stu1_info')['age'])

  先使用shelve方法把字典写入三个文件(不可读乱码),而后使用get方法取值

 

  6,xml模块

  xml是实现不一样语言和程序之间进行数据交换的协议,跟json差很少,但json使用起来更简单。

  列子测试xml文档 xml_lesson

<data>
    <country name="Liechtenstein">
        <rank updated="yes">2</rank>
        <year updated="yes">2012</year>
        <gdppc>141100</gdppc>
        <neighbor direction="E" name="Austria" />
        <neighbor direction="W" name="Switzerland" />
    </country>
    <country name="Singapore">
        <rank updated="yes">5</rank>
        <year updated="yes">2015</year>
        <gdppc>59900</gdppc>
        <neighbor direction="N" name="Malaysia" />
    </country>
    <country name="Panama">
        <rank updated="yes">69</rank>
        <year updated="yes">2015</year>
        <gdppc>13600</gdppc>
        <neighbor direction="W" name="Costa Rica" />
        <neighbor direction="E" name="Colombia" />
    </country>
</data>

  对xml文件进行操做xml_test.py

#使用as能够把比较长的模块简写
import xml.etree.ElementTree as ET

#使用parse解析后赋值给tree对象
tree = ET.parse("xml_lesson")
#getroot拿到跟节点
root = tree.getroot()
print(root.tag)
#data

# for i in root:
#     #print(i.tag)
#     #print(i.attrib)
#     #print(i.text)
#     for j in i:
#         print(j.tag,j.text)



# 遍历xml文档
#
# # 只遍历year 节点
# for node in root.iter('year'):
#     print(node.tag, node.text)
# # ---------------------------------------
#
# import xml.etree.ElementTree as ET
#
# tree = ET.parse("xmltest.xml")
# root = tree.getroot()
#
# # 修改
for node in root.iter('year'):
    new_year = int(node.text) + 1
    node.text = str(new_year)
    node.set("updated", "yes")

#修改后写进去文件名能够重复则覆盖,也能够不重复则新建一个文件
tree.write("xml_lesson")
#
# # 删除node
for country in root.findall('country'):
    rank = int(country.find('rank').text)
    if rank > 50:
        root.remove(country)

tree.write('output.xml')

  生成xml文档xml_create.py

import xml.etree.ElementTree as ET

new_xml = ET.Element("namelist")
name = ET.SubElement(new_xml, "name", attrib={"enrolled": "yes"})
age = ET.SubElement(name, "age", attrib={"checked": "no"})
sex = ET.SubElement(name, "sex")
sex.text = '33'
name2 = ET.SubElement(new_xml, "name", attrib={"enrolled": "no"})
age = ET.SubElement(name2, "age")
age.text = '19'

et = ET.ElementTree(new_xml)  # 生成文档对象
et.write("test.xml", encoding="utf-8", xml_declaration=True)

ET.dump(new_xml)  # 打印生成的格式

  

  7,re模块

  就期本质而言,正则表达式(re)是一种小型的,高度专业化的编程语言,在python中它内嵌在python中经过re模块实现。

  一,re模块的匹配规则及元字符

  re_lesson.py

import re

#彻底匹配若是须要匹配的字符串中间包含其余字符就匹配不到
ret = re.findall('zhangsan','hellozhangsan')
print(ret)
#['zhangsan']

#元字符 .^$+?{}[]|()\
#.通配符能够匹配一个任何字符,没有匹配到返回一个空列表
ret = re.findall('m..g','yueming')
print(ret)
#['ming']

#^以什么开头的
ret = re.findall('^y.e','yueming')
print(ret)
#['yue']

#$以什么结尾的
ret = re.findall('ing$','yuming')
print(ret)
#['ing']

#*表明匹配0次到无穷次
ret = re.findall('d*','sfdgsdddddd')
print(ret)
#['', '', 'd', '', '', 'dddddd', '']

#+表明匹配1到无穷次
ret = re.findall('d+','sfdgsdddddd')
print(ret)
#['d', 'dddddd']

#? 匹配0或者1次
ret = re.findall('ming?','asdhfaming')
print(ret)
#ming

#{}本身定义匹配多少  {0,} == *  0到无穷至关于*
#                 {1,} == +  1到无穷至关于+
#                 {0,1} == ? 0或者1至关于?
# {6} 重复6次 {1,6}能够重复1到6次之间的任何次数
ret = re.findall('ming{0,}','yuemingg')
print(ret)
#['mingg']

ret = re.findall('ming{1,}','yueminggg')
print(ret)
#['minggg']

ret = re.findall('ming{0,1}','yuemin')
print(ret)
#['min']

#PS:默认都是贪婪匹配尽量多地取匹配若是须要惰性匹配在后面加一个? 以下
ret = re.findall('ming{1,}?','yueminggg')
print(ret)
#['ming']

#[]字符集
#起到或的做用
ret = re.findall('x[yz]p','xypuuuxzp')
print(ret)

#使用-表明一个区间
ret = re.findall('[a-z1-9]','abbh1210')
print(ret)

#['a', 'b', 'b', 'h', '1', '2', '1']
#PS:在字符集[]里面除了 - ^ \ 其余的均为普通字符

#^放在字符集里面不是匹配开头而是非
ret = re.findall('q[^a-z]','qa')
print(ret)
#[]

#计算器思路,匹配两个括号中间没有括号的任意字符
#前面\(表明匹配左括号 后面\)表明匹配右括号
#[^()]表明中间没有括号 这里的()由于是在[]里面不须要加\转义
#*表明匹配两个()之间的任意字符
#这样就能取出一个任意长计算字符串最里面括号的那一串字符了
ret = re.findall('\([^()]*\)','12+(34*6+2-5*(2-1))')
print(ret)
#['(2-1)']

#元字符之转义字符\
#反斜杠后面跟元字符去除特殊功能,好比\.就表明字符.
#反斜杠后面跟普通字符实现特殊功能,好比\d
#\d匹配任何十进制数,至关于[0-9]
ret = re.findall('\d','asad12asd2')
print(ret)
#['1', '2', '2']
#\D匹配任意非数字字符,至关于[^0-9]
ret = re.findall('\D+','asad12asd2')
print(ret)
#['asad', 'asd']
#\s匹配任意空白字符,至关于于[\t\n\r\f\v]
ret = re.findall('\s+','hello world')
print(ret)
#\S匹配任意非空白字符,至关于[^\t\n\r\f\v]
ret = re.findall('\S+','hello world')
print(ret)
#\s和\S不经常使用

#\w匹配任意字母数字字符包括下划线,至关于[a-zA-Z0-9_]
ret = re.findall('\w+','hello world')
print(ret)
#['hello', 'world']

#\W匹配任意非字母数字字符,至关于[^a-zA-Z0-9]
ret = re.findall('\W+','hello world#')
print(ret)
#[' ', '#']

#使用\去除特殊符号的特殊功能
ret = re.findall('www\*baidu','www*baidu.com')
print(ret)

#\b匹配一个特殊边界字符,好比空格 & #等
#需求匹配单独的I
#这里须要在\b前面在加一个\再次转义 或者在前面加r表明里面的字符串不作任何转义
#\\表明把\转义为普通的字符\ 在加上b就表明能够匹配空格了
#由于\b不光在re里面有意义一样在python里面也是有意义的
#\b在python里面的意义表明是退格
#print('123\b')输出为12 原本应该输出的3被退格了
ret = re.findall('I\b','hello I am LIST')
print(ret)

#需求匹配\f
#python调用模块re里面也有本身的语法及转义字符
#这里须要加4个\ 由于\\在python里面转义表明一个\
#若是re模块接收到2个\ 转义一下就表明一个普通的\了
ret = re.findall('c\\\\l','abc\le')
print(ret)

#元字符之| 或匹配
ret = re.findall('ka|b','kajkb')
print(ret)
#['ka', 'b']
ret = re.findall('(?P<name>\w+)','abcabc')
print(ret)

#search方法 只取第一个知足条件的 返回的是一个对象
#没有找到返回为空
ret = re.search('\d+','sdasd34sdf13')
print(ret)
#<_sre.SRE_Match object; span=(5, 7), match='34'>
#经过group方法返回对象的结果
print(ret.group())
#34

ret = re.search('(?P<name>[a-z]+)','123asdf43')
print(ret.group())
#asdf


#?P<name>经过分组取对应的信息假设前面是姓名后面是对应的年龄信息
#分组可用于提取url信息
ret = re.search('(?P<name>[a-z]+)\d+','zhangsan16lisi18')
print(ret.group())
#zhangsan16
print(ret.group('name'))
#zhansan

#一样年龄也能够分一个组为id
ret = re.search('(?P<name>[a-z]+)(?P<id>\d+)','zhangsan16lisi18')
print(ret.group('name'))
#zhangsan
print(ret.group('id'))
#16

  

  二,re模块的方法

  re_method.py

import re
#findall 返回全部知足条件的结果,放在一个列表里面,没有结果返回空列表
ret = re.findall('a','abc')
print(ret)
#['a']

#search匹配,只找到第一个匹配返回一个对象
#经过group()方法取得字符串,若是没有匹配返回为空
ret = re.search('a','abc')
print(ret)
#<_sre.SRE_Match object; span=(0, 1), match='a'>
print(ret.group())
#a

#match同search 不一样之处在于match从字符串开始匹配
#至关于使用search匹配加了一个^
ret = re.match('\d+','asda12')
print(ret)
#None
ret = re.match('\d+','12asda12')
print(ret)
#<_sre.SRE_Match object; span=(0, 2), match='12'>

#split分割
#使用空格分割
ret = re.split(' ','hello abc')
print(ret)
#['hello', 'abc']

#使用[]能够定义多个分割符号
ret = re.split('[ |]','hello abc|def')
print(ret)
#['hello', 'abc', 'def']

#分割过程
#1,用a分割由于a左边没有及为空分割后为['','bc']
#2,用b分割既成['', '','c']
ret = re.split('[ab]','abc')
print(ret)
#['', '','c']

#sub替换
#三个参数,源 目标 字符串
#这里使用b替换a
ret = re.sub('a','b','abc')
print(ret)
#bbc
#默认是所有匹配,后面加参数指定匹配次数(使用几率小)
ret = re.sub('\d','A','abc1212324asfd',4)
print(ret)
#abcAAAA324asfd

#subn把匹配的次数打印出来
ret = re.subn('\d','A','abc1212324asfd',4)
print(ret)
#('abcAAAA324asfd', 4)

#compile把匹配规则编译生成一个对象
#调用该对象就是直接使用规则,跟的参数就只有须要匹配的字符串便可
#做用定义匹配规则能够屡次调用
com = re.compile('\d+')
print(com)
#re.compile('\\d+')
ret = com.findall('ad12')
print(ret)
#['12']

#finditer 同findall效果同样 可是返回的是一个迭代器对象不是一个列表
ret = re.finditer('\d','asdasd71623asdjhagsd')
print(ret)
#<callable_iterator object at 0x0000022D562C7240>
#使用for循环加group方法能够取出结果
for item in ret:
    print(item.group())

 

  PS:使用()分组的优先级 

ret = re.findall('www\.(baidu|163)\.com','www.baidu.com')
print(ret)

#['baidu']

  由于使用了()分组 已经匹配到www.baidu.com可是默认优先级是取()里面的因此这里的结果是['baidu']

  在分组()里面的前面加?:去除分组优先级

ret = re.findall('www\.(?:baidu|163)\.com','www.baidu.com')
print(ret)

['www.baidu.com']

  

  分组()补充

#分组()补充
ret = re.findall('(abc)+','abcabcabc')
print(ret)
#输出以下,由于优先匹配一个()内里面的内容
#['abc']
ret = re.findall('(?:abc)+','abcabcabcdsdabc')
print(ret)
#加?:取消优先级输出以下
#['abcabcabc', 'abc']

 

  8,logging模块(重要)

  日志模块,记录信息

  一,简单应用

  logging_test.py

import logging

#默认只打印warning以上信息设置成debug能够打印全部信息
logging.basicConfig(
    level=logging.DEBUG,
    #默认是把日志显示在屏幕上,下面定义写入文件
    #写入文件是追加,原内容不变
    filename="logger.log",
    #如下参数设置为覆盖
    #filemode='w',
    #定义日志格式
    #asctime时间
    #filename执行文件的名称这里是logging_test.py
    #lineno行号
    #message自定义的信息
    format='%(asctime)s %(filename)s [%(lineno)d] %(message)s'
)

logging.debug('debug message')
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical message')

#root是默认的用户名
'''
DEBUG:root:debug message
INFO:root:info message
WARNING:root:warning message
ERROR:root:error message
CRITICAL:root:critical message
'''

  

  二,使用logger对象把日志信息写入到文件的同时显示到屏幕

  logging_test2.py

import logging
#logger对象,使日志既显示的屏幕又输出到文件

logger=logging.getLogger()
#建立实例化对象能够向文件发送内容
fh=logging.FileHandler("test.log")
#建立实例化对象能够向屏幕发送内容
ch=logging.StreamHandler()

#自定义日志格式
fm=logging.Formatter("%(asctime)s %(message)s")

#使用fh和ch吃掉日志格式fm
fh.setFormatter(fm)
ch.setFormatter(fm)

#使用logger分别吃掉fh和ch
logger.addHandler(fh)
logger.addHandler(ch)
#设置日志级别
logger.setLevel("DEBUG")

#----------------------->>

logger.debug("debug message")
logger.info("info message")
logger.warning("warning message")
logger.error("error message")
logger.critical("critical message")

  PS:logger对象使用比basicConfig更多

 

再看一个列子logging_test3.py

import logging
##################################################
#默认是root跟用户加参数设置子用户
logger1 = logging.getLogger('mylogger')
logger1.setLevel(logging.DEBUG)

logger2 = logging.getLogger('mylogger')
logger2.setLevel(logging.INFO)

#建立实例化对象能够向文件发送内容
fh=logging.FileHandler("test_new.log")
#建立实例化对象能够向屏幕发送内容
ch=logging.StreamHandler()

logger1.addHandler(fh)
logger1.addHandler(ch)

logger2.addHandler(fh)
logger2.addHandler(ch)

logger1.debug('logger1 debug message')
logger1.info('logger1 info message')
logger1.warning('logger1 warning message')
logger1.error('logger1 error message')
logger1.critical('logger1 critical message')

logger2.debug('logger2 debug message')
logger2.info('logger2 info message')
logger2.warning('logger2 warning message')
logger2.error('logger2 error message')
logger2.critical('logger2 critical message')

  咱们明明经过logger1.setLevel(logging.DEBUG)将logger1的日志级别设置为了DEBUG,为什么显示的时候没有显示出DEBUG级别的日志信息,而是从INFO级别的日志开始显示呢?

  原来logger1和logger2对应的是同一个Logger实例,只要logging.getLogger(name)中名称参数name相同则返回的Logger实例就是同一个,且仅有一个,也即name与Logger实例一一对应。在logger2实例中经过logger2.setLevel(logging.INFO)设置mylogger的日志级别为logging.INFO,因此最后logger1的输出听从了后来设置的日志级别。

  

  再看一个列子

  logging_test4.py

import logging
##################################################


#默认是root跟用户加参数设置子用户
logger1 = logging.getLogger('mylogger')
logger1.setLevel(logging.DEBUG)

logger2 = logging.getLogger('mylogger')
logger2.setLevel(logging.INFO)

#建立实例化对象能够向文件发送内容
fh=logging.FileHandler("test_new.log")
#建立实例化对象能够向屏幕发送内容
ch=logging.StreamHandler()

logger1.addHandler(fh)
logger1.addHandler(ch)

logger2.addHandler(fh)
logger2.addHandler(ch)
logger=logging.getLogger()
logger.addHandler(ch)
logger.addHandler(fh)
logger.debug('logger debug message')
logger.info('logger info message')
logger.warning('logger warning message')
logger.error('logger error message')
logger.critical('logger critical message')

logger1.debug('logger1 debug message')
logger1.info('logger1 info message')
logger1.warning('logger1 warning message')
logger1.error('logger1 error message')
logger1.critical('logger1 critical message')

  PS:子对象logger1会重复打印两次,由于子在打印的时候回找父若是存在就多打印一次(知道便可,用的较少)

 

  9,configparser模块

   配置文件解析模块

   生成配置文件 config.py

import configparser

#建立一个生产配置文件的实例化对象
#有了这个对象至关于有一个空字典{}
config = configparser.ConfigParser()
config["DEFAULT"] = {'ServerAliveInterval': '45',
                     'Compression': 'yes',
                     'CompressionLevel': '9'}

config['bitbucket.org'] = {}
config['bitbucket.org']['User'] = 'hg'
config['topsecret.server.com'] = {}
topsecret = config['topsecret.server.com']
topsecret['Host Port'] = '50022'  # mutates the parser
topsecret['ForwardX11'] = 'no'  # same here
config['DEFAULT']['ForwardX11'] = 'yes'
with open('example.ini', 'w') as configfile:
    #写入的方式会普通打开文件写入的方式不一样
    config.write(configfile)

生成的配置文件example.ini

[DEFAULT]
compression = yes
serveraliveinterval = 45
compressionlevel = 9
forwardx11 = yes

[bitbucket.org]
user = hg

[topsecret.server.com]
host port = 50022
forwardx11 = no

对配置文件增删改查confile2.py

import configparser

config = configparser.ConfigParser()

#---------------------------------------------查
#未读取配置文件,为空
print(config.sections())   #[]
#读取配置文件
config.read('example.ini')
#默认的不打印,只打印默认之外的块名
print(config.sections())   #['bitbucket.org', 'topsecret.server.com']
#判断对应的块是否在配置文件里面
print('bytebong.com' in config)# False
#取出块下面的某一个值,这里里面不区分大小写
print(config['bitbucket.org']['User']) # hg

print(config['DEFAULT']['Compression']) #yes

print(config['topsecret.server.com']['ForwardX11'])  #no

#遍历对应的模块下面的键
#会默认把default下面的键都遍历处理
for key in config['bitbucket.org']:
    print(key)


# user
# serveraliveinterval
# compression
# compressionlevel
# forwardx11

#options把键取出来生成一个列表
print(config.options('bitbucket.org'))#['user', 'serveraliveinterval', 'compression', 'compressionlevel', 'forwardx11']
#items取出key和value组成元祖再放在列表里面
print(config.items('bitbucket.org'))  #[('serveraliveinterval', '45'), ('compression', 'yes'), ('compressionlevel', '9'), ('forwardx11', 'yes'), ('user', 'hg')]
#取对应模块下面对应的键对应的值
#这里bitbucket.org下面是没有compression这个键的
#可是去默认default下面有,就取到了对应的键值为yes
print(config.get('bitbucket.org','compression'))#yes


#---------------------------------------------删,改,增(config.write(open('i.cfg', "w")))

#增长一个yuan的块
config.add_section('yuan')

#移除topsecret.server.com块
config.remove_section('topsecret.server.com')
#移除块bitbucket.org下面的键值为user的配置
config.remove_option('bitbucket.org','user')
#在块bitbucket.org下面新建一个键为k1键值为1111的配置
config.set('bitbucket.org','k1','11111')

#修改成写到一个新的文件
#使用open('i.cfg', "w")代替 with open('i.cfg','w') as f:
#能够这样写,不须要关闭
config.write(open('i.cfg', "w"))

生成的新文件i.cfg

[DEFAULT]
compression = yes
serveraliveinterval = 45
compressionlevel = 9
forwardx11 = yes

[bitbucket.org]
k1 = 11111

[yuan]

  

  10,hashlib模块

  用于加密相关操做,3.x里代替了md5模块和sha模块,主要提供SHA1,SHA224,SHA256,SHA384,SHA512,MD5算法

  hashlib_test.py

import hashlib

obj=hashlib.md5()

obj.update("admin".encode('utf8'))

print(obj.hexdigest()) #5d41402abc4b2a76b9719d911017c592

#这一步是在字符串admin基础上作的,至关于对字符串'adminroot'加密
obj.update('root'.encode('utf8'))
print(obj.hexdigest()) #4b3626865dc6d5cfe1c60b855e68634a

#sha256和md5用法是同样的
m = hashlib.sha256()

m.update('admin'.encode('utf8'))

print(m.hexdigest())

#8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918
相关文章
相关标签/搜索