模块
一、定义:
模块:用来从逻辑上组织python代码(变量,函数,类,逻辑:实现一个功能),
本质就是.py结尾的python文件(文件名:test.py,对应模块名:test)
包:用来从逻辑上组织模块的,本质就是一个目录(必须带有一个__init__.py的文件)
二、导入方法
import module_alex,
调用:print(module_alex.name)
module_alex.say_hello()
导入多个模块:import module1_name,import module2_name
把module_alex中的所有代码导入:from module_alex import *(不建议使用*,
它的本质是复制maodule_alex中的代码到当前程序,变量有重复的话执行当前程序的变量)
from module_alex import logger as logger_alex (起个别名)
导入多个:from module_alex import m1,m2,m3
三、import本质(路径搜索和搜索路径)
import module_alex将module_alex的所有代码解释一遍并赋值给一个变量module_alex,调用通过module_alex.***的形式
(import test test="test.py all code")
(from test import name name="code")
导入模块的本质就是把python文件解释一遍。
import module_alex--->module_alex.py(是文件就一定有路径)---->module_alex.py的路径---->sys.path(先在当前位置找,再在系统环境变量中找)
导入包的本质就是执行该包下面的__init__.py文件
四、导入优化
from module_test import test
main.py
import sys,os
print(sys.path) x=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(x)
import module_alex
module_alex.say_hello()
main
__init__.py
print("from the package_test") #import test1 #test="test1.py all code".test1.test()
from.import test1 #相对导入,从当前目录下导入test1,相对于__init__的路径
init
test1.py
def test():
print("in the test1")
test1
module_test.py
def test():
print("in the module_test")
module_test
test.py
import module_test
#from module_test import test
def logger():
module_test.test()
print('in the logger') def search():
module_test.test()
print("in the search")
test
module_alex.py
name="alex"
def say_hello():
print("hello alex")
def logger():
pass
def running():
pass
module_alex
p_test.py
import package_test
#1.run __init__.py--->test1="test1.py all code".test1 package_test.test1.test()
p_test
五、模块的分类:
a:标准库(内置模块)、b:开源模块(第三方模块)、c:自定义模块
1.time与datetime
在Python中,通常有这几种方式来表示时间:1)时间戳2)格式化的时间字符串3)元组(struct_time)共九个元素。由于Python的time模块实现主要调用C库,所以各个平台可能有所不同。
UTC(Coordinated Universal Time,世界协调时)亦即格林威治天文时间,世界标准时间。在中国为UTC+8。DST(Daylight Saving Time)即夏令时。
时间戳(timestamp)的方式:通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。我们运行“type(time.time())”,返回的是float类型。返回时间戳方式的函数主要有time(),clock()等。
元组(struct_time)方式:struct_time元组共有9个元素,返回struct_time的函数主要有gmtime(),localtime(),strptime()。
import time
print(time.localtime())
'''--->time.struct_time(tm_year=2017, tm_mon=10, tm_mday=24,
tm_hour=10, tm_min=36, tm_sec=20, tm_wday=1, tm_yday=297, tm_isdst=0)''' time:
import time
print(time.localtime())
'''--->time.struct_time(tm_year=2017, tm_mon=10, tm_mday=24,
tm_hour=10, tm_min=36, tm_sec=20, tm_wday=1, tm_yday=297, tm_isdst=0)''' #Variables:
print(help(time))
print(time.timezone) # difference in seconds between UTC and local standard time
print(time.altzone) #difference in seconds between UTC and local DST time
print(time.daylight) #whether local time should reflect DST
#Functions:
print(time.time()) # return current time in seconds since the Epoch as a float
time.sleep(2) # delay for a number of seconds given as a float
print(time.gmtime())#将时间戳转化为struct_time,不传入参数的话将本地时间换算成UCT时间,传入参数的话,"1970"+参数
print(time.localtime())#将时间戳转化为struct_time,不传入参数的话就是本地时间,传入参数同上,不过hour+8 x=time.localtime()
print(x.tm_year) #提取"年" print(time.mktime(x)) #元组形式转化为时间戳
print(time.strftime("%Y-%m-%d %H:%M:%S",x)) #元组形式转化为格式化字符串
#%Y相当于x.tm_year %m相当于x.tm_mon
print(time.strptime("2017-10-24 13:36:46","%Y-%m-%d %H:%M:%S")) #格式化字符串转化为元组形式
#以后面的格式到前边找对应的值,x.tm_year=2017,x.tm_mon=10 print(time.asctime())#将元组转化为字符串的格式,不写参数传入的就是本地时间
print(time.ctime())#将时间戳转化为字符串的格式,不写参数传入的就是本地时间 import datetime
print(datetime.datetime.now()) # 返回 2017-10-24 14:52:46.098161
print(datetime.date.fromtimestamp(time.time()) ) # 时间戳直接转成日期格式 2017-10-24
print("-----")
print(datetime.datetime.now() + datetime.timedelta(3)) #当前时间+3天
print(datetime.datetime.now() + datetime.timedelta(-3)) #当前时间-3天
print(datetime.datetime.now() + datetime.timedelta(hours=3)) #当前时间+3小时
print(datetime.datetime.now() + datetime.timedelta(minutes=30)) #当前时间+30分
print("-----")
c_time = datetime.datetime.now()
print(c_time.replace(minute=3,hour=12)) #时间替换
time
strftime(“格式”,struct_time)--->“格式化的字符串”
strptime(“格式化的字符串”,“格式”)--->struct_time
格式参照:
%
a 本地(locale)简化星期名称
%
A 本地完整星期名称
%
b 本地简化月份名称
%
B 本地完整月份名称
%
c 本地相应的日期和时间表示
%
d 一个月中的第几天(
01
-
31
)
%
H 一天中的第几个小时(
24
小时制,
00
-
23
)
%
I 第几个小时(
12
小时制,
01
-
12
)
%
j 一年中的第几天(
001
-
366
)
%
m 月份(
01
-
12
)
%
M 分钟数(
00
-
59
)
%
p 本地am或者pm的相应符
%
S 秒(
01
-
61
)
%
U 一年中的星期数。(
00
-
53
星期天是一个星期的开始。)第一个星期天之前的所有天数都放在第
0
周。
%
w 一个星期中的第几天(
0
-
6
,
0
是星期天)
%
W 和
%
U基本相同,不同的是
%
W以星期一为一个星期的开始。
%
x 本地相应日期
%
X 本地相应时间
%
y 去掉世纪的年份(
00
-
99
)
%
Y 完整的年份
%
Z 时区的名字(如果不存在为空字符)
%
%
‘
%
’字符
2.random模块
import random
print(random.random())#随机浮点值0-1之间 print(random.randint(1,3))#随机1-3之间的整数,3能取到
#random.randint()的函数原型为:random.randint(a, b),用于生成一个指定范围内的整数。
# 其中参数a是下限,参数b是上限,生成的随机数n: a <= n <= b print(random.randrange(1,3))#随机1-3之间的整数,3不能取到,1能取到
#random.randrange的函数原型为:random.randrange([start], stop[, step]),
# 从指定范围内,按指定基数递增的集合中 获取一个随机数。如:random.randrange(10, 100, 2),
# 结果相当于从[10, 12, 14, 16, ... 96, 98]序列中获取一个随机数。
# random.randrange(10, 100, 2)在结果上与 random.choice(range(10, 100, 2) 等效。 print(random.choice("hello"))#序列,字符串,列表,元组
# 其函数原型为:random.choice(sequence)。参数sequence表示一个有序类型。
# 这里要说明一下:sequence在python不是一种特定的类型,而是泛指一系列的类型。
# list, tuple, 字符串都属于sequence。有关sequence可以查看python手册数据模型这一章。 print(random.sample("hello",4))#第一个变量序列,字符串,列表,元组,第二个定义一个长度,随机取几位返回
#random.sample的函数原型为:random.sample(sequence, k),从指定序列中随机获取指定长度的片断。sample函数不会修改原有序列。
list = [1, 2, 3, 4, 5, 6, 7, 8]
slice = random.sample(list, 5) # 从list中随机获取5个元素,作为一个片断返回
print(slice)
print(list) # 原有序列并没有改变 print(random.uniform(1,3))#random不能指定区间,uniform可以指定 l=[1,2,3,4,5,6]
random.shuffle(l)#洗牌功能
print(l)
print("------")
import random
# 随机整数:
print(random.randint(0, 99)) #
# 随机选取0到100间的偶数:
print(random.randrange(0, 101, 2)) #
# 随机浮点数:
print(random.random()) # 0.2746445568079129
print(random.uniform(1, 10)) # 9.887001463194844
# 随机字符:
print(random.choice('abcdefg&#%^*f')) # f
# 多个字符中选取特定数量的字符:
print(random.sample('abcdefghij', 3)) # ['f', 'h', 'd']
# 随机选取字符串:
print(random.choice(['apple', 'pear', 'peach', 'orange', 'lemon'])) # apple
# 洗牌#
items = [1, 2, 3, 4, 5, 6, 7]
print(items) # [1, 2, 3, 4, 5, 6, 7]
random.shuffle(items)
print(items) # [1, 4, 7, 2, 5, 3, 6]
print("======")
#验证码
checkcode=""
for i in range(4):
#i=0
current=random.randrange(0,4)
#字母
if current==i:
tmp=chr(random.randint(65,90))
#数字
else:
tmp=random.randint(0,9)
checkcode+=str(tmp)
print(checkcode)
random
3.os模块
import os
print(os.getcwd())#获取当前工作目录,即当前python脚本工作的目录路径
# os.chdir("E:\\pycharm\\s14\\")
os.chdir(r"E:\pycharm\s14")
print(os.getcwd())# 改变当前脚本工作目录;相当于shell下cd
print(os.curdir) # 返回当前目录: ('.')
print(os.pardir) #获取当前目录的父目录字符串名:('..')
#os.makedirs(r'E:\a\b\c\d') # 可生成多层递归目录
#os.removedirs(r'E:\a\b\c\d') #若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推,清理空文件夹
#os.mkdir(r'E:\a\b') # 生成单级目录;相当于shell中mkdir dirname
#os.rmdir(r'E:\a\b') # 删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
print(os.listdir(".")) #列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印-->
# ['.idea', 'day1', 'day2', 'day3', 'day4', 'day5']
#os.remove() # 删除一个文件
#os.rename(r"E:\pycharm\s14\day5\y_test.py",r"E:\pycharm\s14\day5\p_test.py") #重命名文件/目录
print(os.stat('day5')) #获取文件/目录信息
print(os.sep)#输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/"
print(os.linesep) # 输出当前平台使用的行终止符,win下为"\r\n",Linux下为"\n"
#print(os.environ)#获取系统环境变量
print(os.pathsep) #输出用于分割文件路径的字符串 windows中';'
print(os.name) #输出字符串指示当前使用平台。win->'nt'; Linux->'posix'
#os.system("dir") #运行shell命令,直接显示
#os.system("ipconfig /all")
print(os.path.abspath(r"E:\pycharm\day5\os_moduel\os.py")) #返回规范化的绝对路径
print("=====")
print(os.path.split(r"E:\a\b\c\d.txt")) # 将path分割成目录和文件名二元组返回
print(os.path.dirname(r"E:\a\b\c\d.txt")) #返回path的目录。其实就是os.path.split("path")的第一个元素
print(os.path.basename(r"E:\a\b\c\d.txt")) # 返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。
# 即os.path.split("path")的第二个元素
#以上三中方法都可以在目录不存在的情况下进行
print(os.path.exists(r"E:\a")) # 如果path存在,返回True;如果path不存在,返回False
print(os.path.isabs(r"a\b")) # 如果path是绝对路径,返回True
print(os.path.isfile(r"E:\a\1.txt")) # 如果path是一个存在的文件,返回True。否则返回False,不存在文件False
print(os.path.isdir(r"E:\a")) # 如果path是一个存在的目录,则返回True。否则返回False,不存在目录False
print(os.path.join(r"C:",r"a",r"b",r"a.txt"))# 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
print(os.path.getatime(r"E:\a\1.txt")) # 返回path所指向的文件或者目录的最后存取时间 ,文件必须存在
print(os.path.getmtime(r"E:\a\1.txt") ) #返回path所指向的文件或者目录的最后修改时间
os_
更多https://docs.python.org/2/library/os.html?highlight=os#module-os
4.sys模块
import sys
print(sys.argv) # 命令行参数List,,在终端运行后加参数,第一个元素是程序本身路径
#print(sys.exit()) #退出程序,正常退出时exit(0)
print(sys.version) #获取Python解释程序的版本信息
print(sys.maxsize)
print(sys.path) #返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
print(sys.platform) #返回操作系统平台名称
print(sys.stdout.write('please:'))
val = sys.stdin.readline()[:-1]
sys_
5.shutil模块
http://www.cnblogs.com/wupeiqi/articles/4963027.html
高级的 文件、文件夹、压缩包 处理模块
shutil.copyfileobj(fsrc, fdst[, length])
将文件内容拷贝到另一个文件中,可以部分内容
shutil.copyfile(src, dst)
拷贝文件
shutil.copymode(src, dst)
仅拷贝权限。内容、组、用户均不变
shutil.copystat(src, dst)
拷贝状态的信息,包括:mode bits, atime, mtime, flags
shutil.copy(src, dst)
拷贝文件和权限
shutil.copy2(src, dst)
拷贝文件和状态信息
shutil.ignore_patterns(*patterns)
shutil.copytree(src, dst, symlinks=False, ignore=None)
递归的去拷贝文件
例如:copytree(source, destination, ignore=ignore_patterns('*.pyc', 'tmp*'))
shutil.rmtree(path[, ignore_errors[, onerror]])
递归的去删除文件
shutil.move(src, dst)
递归的去移动文件
shutil.make_archive(base_name, format,...)
创建压缩包并返回文件路径,例如:zip、tar
- base_name: 压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径,
如:www =>保存至当前路径
如:/Users/wupeiqi/www =>保存至/Users/wupeiqi/ - format: 压缩包种类,“zip”, “tar”, “bztar”,“gztar”
- root_dir: 要压缩的文件夹路径(默认当前目录)
- owner: 用户,默认当前用户
- group: 组,默认当前组
- logger: 用于记录日志,通常是logging.Logger对象
shutil 对压缩包的处理是调用 zipfile 和 tarfile 两个模块来进行的,详细:
import zipfile # 压缩
z = zipfile.ZipFile('laxi.zip', 'w')
z.write('a.log')
z.write('data.data')
z.close() # 解压
z = zipfile.ZipFile('laxi.zip', 'r')
z.extractall()
z.close()
zipfile
import tarfile # 压缩
tar = tarfile.open('your.tar','w')
tar.add('/Users/wupeiqi/PycharmProjects/bbs2.zip', arcname='bbs2.zip')
tar.add('/Users/wupeiqi/PycharmProjects/cmdb.zip', arcname='cmdb.zip')
tar.close() # 解压
tar = tarfile.open('your.tar','r')
tar.extractall() # 可设置解压地址
tar.close()
tarfile
import shutil
# f1=open("本节笔记",encoding="utf-8")
# f2=open("笔记2","w",encoding="utf-8")
# shutil.copyfileobj(f1,f2) #shutil.copyfile("笔记2","笔记3") #shutil.make_archive("shutil_archive_test","zip","E:\pycharm\s14\day5") import zipfile
z = zipfile.ZipFile("day5.zip","w")
z.write("p_test.py")
print("---")
z.write("笔记2")
z.close()
shutil_
6.shelve模块
shelve模块是一个简单的key-value将内存数据通过文件持久化的模块,可以持久化任何pickle可支持的python数据格式。
import shelve,datetime d = shelve.open('shelve_test') # 打开一个文件 # info={"age":22,"salary":"50w"}
#
# name = ["alex", "rain", "test"]
# d["test"] = name # 持久化列表
# d["name"] = name # 持久dict
# d["info"] =info
# d["date"]=datetime.datetime.now()
# d.close() print(d.get("name"))
print(d.get("info"))
print(d.get("date"))
shelve_
7.xml模块
xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单,不过,古时候,在json还没诞生的黑暗年代,
大家只能选择用xml呀,至今很多传统公司如金融行业的很多系统的接口还主要是xml。
xml的格式如下,就是通过<>节点来区别数据结构的:
<?xml version='1.0' encoding='utf-8'?>
<data>
<country name="Liechtenstein">
<rank updated="yes">2</rank>
<year updated_by="alex">2009</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_by="alex">2012</year>
<gdppc>59900</gdppc>
<neighbor direction="N" name="Malaysia" />
</country>
<country name="Panama">
<rank updated="yes">69</rank>
<year updated_by="alex">2012</year>
<gdppc>13600</gdppc>
<neighbor direction="W" name="Costa Rica" />
<neighbor direction="E" name="Colombia" />
<info>
<population>8</population>
<size>960</size>
</info>
</country>
</data>
格式
xml协议在各个语言里的都 是支持的,在python中可以用以下模块操作xml
import xml.etree.ElementTree as ET tree = ET.parse("xmltest.xml") #写上要处理的文件名
root = tree.getroot()
print(root)
print(root.tag) #标签名 # 遍历xml文档
for child in root:
print(child.tag, child.attrib) #子标签,attrib属性
for i in child:
print(i.tag, i.text)
for j in i:
print(j.tag,j.text) # # 只遍历year 节点
# for node in root.iter('year'):
# print(node.tag, node.text)
xml_handle
修改和删除xml文档内容
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 #把年+1
# node.text = str(new_year)
# node.set("updated_by", "alex") #加属性
#
# tree.write("xmltest.xml") # 删除node
for country in root.findall('country'):
rank = int(country.find('rank').text)
if rank > 50:
root.remove(country) tree.write('output.xml')
xml_modify
自己创建xml文档
import xml.etree.ElementTree as ET new_xml = ET.Element("personinfolist") #根节点
personinfo = ET.SubElement(new_xml, "personinfo", attrib={"enrolled": "yes"}) #new_xml的子节点
name = ET.SubElement(personinfo, "name")
name.text="alex"
age = ET.SubElement(personinfo, "age", attrib={"checked": "no"})#personinfo的子节点
sex = ET.SubElement(personinfo, "sex")
age.text = ''#赋值
personinfo2 = ET.SubElement(new_xml, "personinfo", attrib={"enrolled": "no"})
name = ET.SubElement(personinfo2, "name")
name.text="jyh"
age = ET.SubElement(personinfo2, "age")
age.text = '' et = ET.ElementTree(new_xml) # 生成文档对象
et.write("test.xml", encoding="utf-8", xml_declaration=True) #xml_declaration=True,声明xml格式 ET.dump(new_xml) # 打印生成的格式
xml_create
8.PyYAML模块
Python也可以很容易的处理ymal文档格式,只不过需要安装一个模块,参考文档:http://pyyaml.org/wiki/PyYAMLDocumentation,可以做配置文件
9.ConfigParser模块
用于生成和修改常见配置文档,当前模块的名称在 python 3.x 版本中变更为 configparser。
来看一个好多软件的常见文档格式如下(与MySQL格式一样)
[DEFAULT]
ServerAliveInterval = 45
Compression = yes
CompressionLevel = 9
ForwardX11 = yes [bitbucket.org]
User = hg [topsecret.server.com]
Port = 50022
ForwardX11 = no
conf
如果想用python生成一个这样的文档怎么做呢?
import configparser #ConfigParser in python 2.x config = configparser.ConfigParser()
config["DEFAULT"] = {'ServerAliveInterval': '',
'Compression': 'yes',
'CompressionLevel': ''} config['bitbucket.org'] = {}
config['bitbucket.org']['User'] = 'hg' config['topsecret.server.com'] = {}
config['topsecret.server.com']['Host Port'] = '' # mutates the parser
config['topsecret.server.com']['ForwardX11'] = 'no' # same here config['DEFAULT']['ForwardX11'] = 'yes' with open('example.ini', 'w') as configfile:
config.write(configfile)
conf_create
写完了还可以再读出来哈。
>>> import configparser
>>> config = configparser.ConfigParser()
>>> config.sections()
[]
>>> config.read('example.ini')
['example.ini']
>>> config.sections()
['bitbucket.org', 'topsecret.server.com']
>>> 'bitbucket.org' in config
True
>>> 'bytebong.com' in config
False
>>> config['bitbucket.org']['User']
'hg'
>>> config['DEFAULT']['Compression']
'yes'
>>> topsecret = config['topsecret.server.com']
>>> topsecret['ForwardX11']
'no'
>>> topsecret['Port']
''
>>> for key in config['bitbucket.org']: print(key)
...
user
compressionlevel
serveraliveinterval
compression
forwardx11
>>> config['bitbucket.org']['ForwardX11']
'yes'
conf_read
configparser增删改查语法
[section1]
k1 = v1
k2:v2 [section2]
k1 = v1 import ConfigParser config = ConfigParser.ConfigParser()
config.read('i.cfg') # ########## 读 ##########
#secs = config.sections()
#print secs
#options = config.options('group2')
#print options #item_list = config.items('group2')
#print item_list #val = config.get('group1','key')
#val = config.getint('group1','key') # ########## 改写 ##########
#sec = config.remove_section('group1')
#config.write(open('i.cfg', "w")) #sec = config.has_section('wupeiqi')
#sec = config.add_section('wupeiqi')
#config.write(open('i.cfg', "w")) #config.set('group2','k1',11111)
#config.write(open('i.cfg', "w")) #config.remove_option('group2','age')
#config.write(open('i.cfg', "w"))
conf_handle
10.hashlib模块
用于加密相关的操作,3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法(都是基于hash的,SHA比MD5更安全)
import hashlib
m=hashlib.md5()
m.update(b"Hello")
print(m.hexdigest()) #16进制的格式
m.update("It's me天王盖地虎".encode(encoding="utf-8")) #实际上是“HelloIt's me天王盖地虎”
print(m.hexdigest())
#m.update(b"It's been a long time since we spoken...")
#print(m.hexdigest()) m2=hashlib.md5()
m2.update(b"HelloIt's me")
print(m.hexdigest()) s2=hashlib.sha1()
s2.update(b"HelloIt's me")
print(s2.hexdigest())
print("====")
import hmac
h=hmac.new(b"","you are 250你是".encode(encoding="utf-8"))#在3.0里,encode一下就是bytes了
print(h.hexdigest())
hashlib_handle
import hashlib m = hashlib.md5()
m.update(b"Hello")
m.update(b"It's me")
print(m.digest())
m.update(b"It's been a long time since last time we ...") print(m.digest()) #2进制格式hash
print(len(m.hexdigest())) #16进制格式hash
'''
def digest(self, *args, **kwargs): # real signature unknown
""" Return the digest value as a string of binary data. """
pass def hexdigest(self, *args, **kwargs): # real signature unknown
""" Return the digest value as a string of hexadecimal digits. """
pass '''
import hashlib # ######## md5 ######## hash = hashlib.md5()
hash.update('admin')
print(hash.hexdigest()) # ######## sha1 ######## hash = hashlib.sha1()
hash.update('admin')
print(hash.hexdigest()) # ######## sha256 ######## hash = hashlib.sha256()
hash.update('admin')
print(hash.hexdigest()) # ######## sha384 ######## hash = hashlib.sha384()
hash.update('admin')
print(hash.hexdigest()) # ######## sha512 ######## hash = hashlib.sha512()
hash.update('admin')
print(hash.hexdigest())
还不够吊?python 还有一个 hmac 模块,它内部对我们创建 key 和 内容 再进行处理然后再加密
散列消息鉴别码,简称HMAC,是一种基于消息鉴别码MAC(Message Authentication Code)的鉴别机制。使用HMAC时,消息通讯的双方,通过验证消息中加入的鉴别密钥K来鉴别消息的真伪;
一般用于网络通信中消息加密,前提是双方先要约定好key,就像接头暗号一样,然后消息发送把用key把消息加密,接收方用key + 消息明文再加密,拿加密后的值 跟 发送者的相对比是否相等,
这样就能验证消息的真实性,及发送者的合法性了。
import hmac
h = hmac.new(b'天王盖地虎', b'宝塔镇河妖')
print h.hexdigest()
更多关于md5,sha1,sha256等介绍的文章看这里https://www.tbs-certificates.co.uk/FAQ/en/sha256.html
11.正则表达式
使用不难,难在匹配格式。爬虫需要精通。
又返回就匹配到了,没反应就没有匹配到
前边是格式,后边是字符串(套路)
常用正则表达式符号
'.' 默认匹配除\n之外的任意一个字符,若指定flag DOTALL,则匹配任意字符,包括换行
'^' 匹配字符开头,若指定flags MULTILINE,这种也可以匹配上(r"^a","\nabc\neee",flags=re.MULTILINE)
'$' 匹配字符结尾,或e.search("foo$","bfoo\nsdfsf",flags=re.MULTILINE).group()也可以
'*' 匹配*号前的字符0次或多次,re.findall("ab*","cabb3abcbbac") 结果为['abb', 'ab', 'a']
'+' 匹配前一个字符1次或多次,re.findall("ab+","ab+cd+abb+bba") 结果['ab', 'abb']
'?' 匹配前一个字符1次或0次
'{m}' 匹配前一个字符m次
'{n,m}' 匹配前一个字符n到m次,re.findall("ab{1,3}","abb abc abbcbbb") 结果'abb', 'ab', 'abb']
'|' 匹配|左或|右的字符,re.search("abc|ABC","ABCBabcCD").group() 结果'ABC'
'(...)' 分组匹配,re.search("(abc){2}a(123|456)c", "abcabca456c").group() 结果 abcabca456c '\A' 只从字符开头匹配,re.search("\Aabc","alexabc") 是匹配不到的
'\Z' 匹配字符结尾,同$
'\d' 匹配数字0-9
'\D' 匹配非数字
'\w' 匹配[A-Za-z0-9]
'\W' 匹配非[A-Za-z0-9]
's' 匹配空白字符、\t、\n、\r , re.search("\s+","ab\tc1\n3").group() 结果 '\t' '(?P<name>...)' 分组匹配 re.search("(?P<province>[0-9]{4})(?P<city>[0-9]{2})(?P<birthday>[0-9]{4})","").groupdict("city") 结果{'province': '', 'city': '', 'birthday': ''}
re
match套路从开头搜索,search套路从整个文本中搜索
多个匹配到第一个就返回
findall套路
========================================
========================================
split套路
sub套路
最常用的匹配语法:
1.re.match 从头开始匹配
2.re.search 匹配包含
3.re.findall 把所有匹配到的字符放到以列表中的元素返回
4.re.splitall 以匹配到的字符当做列表分隔符
5.re.sub 匹配字符并替换
与大多数编程语言相同,正则表达式里使用"\"作为转义字符,这就可能造成反斜杠困扰。假如你需要匹配文本中的字符"\",
那么使用编程语言表示的正则表达式里将需要4个反斜杠"\\\\":前两个和后两个分别用于在编程语言里转义成反斜杠,
转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。Python里的原生字符串很好地解决了这个问题,这个例子中的正则表达式可以使用r"\\"表示。
同样,匹配一个数字的"\\d"可以写成r"\d"。有了原生字符串,你再也不用担心是不是漏写了反斜杠,写出来的表达式也更直观。
仅需轻轻知道的几个匹配模式
1.re.I(re.IGNORECASE): 忽略大小写(括号内是完整写法,下同)
2.M(MULTILINE): 多行模式,改变
'^'
和
'$'
的行为
3.S(DOTALL): 点任意匹配模式,改变
'.'
的行为
本节作业
开发一个简单的python计算器
- 实现加减乘除及拓号优先级解析
- 用户输入 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )等类似公式后,
- 必须自己解析里面的(),+,-,*,/符号和公式(不能调用eval等类似功能偷懒实现),运算后得出结果,结果必须与真实的计算器所得出的结果一致
思路:
1.先用正则表达式匹配到最里层的括号所包括的不带括号的表达式
2.再把数据量变小(判断里面是否有括号,把加减运算和乘除运算单独放到两个函数里去做)
hint:
re.search(r'\([^()]+\)',s).group()
'(-40/5)'