Python基础(六)模块与包

模块

概念

在Python中,一个.py文件就称之为一个模块(Module)

模块能定义函数,类和变量,模块里也能包含可执行的代码。

作用:提高代码的可维护性和复用性

分类:

  1 使用python编写的.py文件 

  2 已被编译为共享库或DLL的C或C++扩展

  3 把一系列模块组织到一起的文件夹(注:文件夹下有一个__init__.py文件,该文件夹称之为包)

  4 使用C编写并链接到python解释器的内置模块

注意:我们自定义的模块名不应该与python内置模块重名

import

import module1[, module2[,... moduleN]

import导入时会执行被导入的py文件,并将模块名作为变量名,在内存中开辟空间(当模块是第一次被导入时才会执行其py文件,重复导入会直接引用内存中已加载好的结果)

导入文件可以理解为把那个文件的代码粘贴过来

可以为模块设置别名

import module1 as m

from import

#导入模块中的一部分内容
from modname import name1[, name2[, ... nameN]]

#导入模块中的所有内容(不推荐使用,有可能会覆盖掉你之前已经定义的变量。而且可读性极差)
from modname import *

模块搜索路径

  内存中已经加载的模块->内置模块->sys.path路径中包含的模块

  python解释器在启动时会自动加载一些模块到内存中,可以使用sys.modules查看

  sys.path中按照从左到右的顺序查找,位于前的优先被查找。

  import会将被执行文件的目录添加到sys.path(返回列表)中作为第一个元素优先查找

解决模块导入问题:

 

模块与脚本

脚本:一个文件就是整个程序,用来被执行

模块:文件中存放着一堆功能,用来被导入使用

 

python为为我们内置了全局变量__name__

当文件被当做脚本执行时:__name__ 等于'__main__'

当文件被当做模块导入时:__name__等于模块名

if __name__ = ‘__main__’

用于判别当前文件是否是被执行文件,如果是则调用该if下方的代码块,如果不是,则不执行该if下方的代码块。

常用模块中函数的调试等(最好将执行操作都写在该if下)

包是一个分层次的文件目录结构,用来管理和组织不同的模块。它定义了一个由模块及子包,和子包下的子包等组成的 Python 的应用环境。

简单来说,包就是文件夹,但该文件夹下必须存在 __init__.py 文件, 该文件的内容可以为空。

__init__.py 用于标识当前文件夹是一个包。调用包就是执行包下的__init__.py文件

time模块

python中时间的表示方式:

  时间戳:表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。我们运行“type(time.time())”,返回的是float类型。

  结构化时间(struct_time):struct_time元组共有9个元素(年,月,日,时,分,秒,一年中第几周,一年中第几天,夏令时)

  时间字符串:生活中常见的表示时间的格式

import time

print(time.time()) #时间戳 1569669433.9596636

print(time.localtime()) #本地时区的struct_time
print(time.gmtime()) #UTC(0时区)的struct_time

print(time.strftime('%Y-%m-%d %X')) #格式化的时间字符串 2019-09-28 19:17:14 
Commonly used format codes:
    
    %Y  Year with century as a decimal number.
    %m  Month as a decimal number [01,12].
    %d  Day of the month as a decimal number [01,31].
    %H  Hour (24-hour clock) as a decimal number [00,23].
    %M  Minute as a decimal number [00,59].
    %S  Second as a decimal number [00,61].
    %z  Time zone offset from UTC.
    %a  Locale's abbreviated weekday name.
    %A  Locale's full weekday name.
    %b  Locale's abbreviated month name.
    %B  Locale's full month name.
    %c  Locale's appropriate date and time representation.
    %I  Hour (12-hour clock) as a decimal number [01,12].
    %p  Locale's equivalent of either AM or PM.
格式化字符串的时间格式

 

 

 

# localtime([secs])
# localtime()将一个时间戳转换为当前时区的struct_time.如果secs参数未提供,则以当前时间为准。
print(time.localtime())
print(time.localtime(1569669433.9596636))

# gmtime([secs])
# gmtime()方法是将一个时间戳转换为UTC时区(0时区)的struct_time。
print(time.gmtime())

# 将一个struct_time转化为时间戳
print(time.mktime(time.localtime()))

# strftime(format[, t])
# 将时间元组转换为格式化的字符串,如果t未指定,将传入time.localtime();
# 如果元组中任何一个元素越界,ValueError的错误将会被抛出。
print(time.strftime('%Y-%m--%d %X', time.localtime())) #2019-09--28 19:29:06

# strptime(string[, format])
# 在这个函数中,format默认为:"%a %b %d %H:%M:%S %Y"
# 把一个格式化时间字符串转化为struct_time
print(time.strptime('2019-9-28 19:30:30', '%Y-%m-%d %X'))
View Code

 

 

 1 # asctime([t])
 2 # 把一个表示时间的元组或者struct_time进行转换,
 3 # 如果没有参数,将会将time.localtime()作为参数传入
 4 print(time.asctime()) #Sat Sep 28 19:35:37 2019
 5 
 6 # ctime([secs])
 7 #  把一个时间戳转化为time.asctime()的形式
 8 #  如果参数未给或者为None的时候,将会默认time.time()为参数。
 9 #  它的作用相当于time.asctime(time.localtime(secs))
10 print(time.ctime()) #Sat Sep 28 19:38:25 2019
View Code
#--------------------------其他用法

#sleep(secs)
# 线程推迟指定的时间运行,单位为秒
time.sleep(2)
print('hello, world')

clock()
# 这个需要注意,在不同的系统上含义不同。在UNIX系统上,它返回的是“进程时间”,它是用秒表示的浮点数(时间戳)。
# 而在WINDOWS中,第一次调用,返回的是进程运行的实际时间。而第二次之后的调用是自第一次调用以后到现在的运行时间,即两次时间差。

  

random模块

import random

print(random.random()) #(0,1] float

print(random.randint(1,3)) #[1,3] int

print(random.randrange(1,3)) #(1,3] int

print(random.choice([1, 'a', 3, 'belief']))

print(random.uniform(1,2)) #1.2939270134537115

s = [11, 22, 33, 44, 55]
random.shuffle(s)
print(s)
 1 import random
 2 
 3 def ver_code():
 4     res = ''
 5     for i in range(4):
 6         n = random.randint(0,9)
 7         s = chr(random.randint(65,90)) #A-Z
 8         ss = chr(random.randint(97,122)) #a-z
 9         r = random.choice([n, s, ss])
10         res += str(r)
11     return res
12 
13 # print(chr(65),chr(90),chr(97),chr(122))
14 print(ver_code())
随机验证码

 

os模块

OS是与操作系统交互的模块

 1 os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径
 2 os.chdir("dirname")  改变当前脚本工作目录;相当于shell下cd
 3 os.curdir  返回当前目录: ('.')
 4 os.pardir  获取当前目录的父目录字符串名:('..')
 5 os.makedirs('dirname1/dirname2')    可生成多层递归目录
 6 os.removedirs('dirname1')    若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
 7 os.mkdir('dirname')    生成单级目录;相当于shell中mkdir dirname
 8 os.rmdir('dirname')    删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
 9 os.listdir('dirname')    列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
10 os.remove()  删除一个文件
11 os.rename("oldname","newname")  重命名文件/目录
12 os.stat('path/filename')  获取文件/目录信息
13 os.sep    输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/"
14 os.linesep    输出当前平台使用的行终止符,win下为"\t\n",Linux下为"\n"
15 os.pathsep    输出用于分割文件路径的字符串 win下为;,Linux下为:
16 os.name    输出字符串指示当前使用平台。win->'nt'; Linux->'posix'
17 os.system("bash command")  运行shell命令,直接显示
18 os.environ  获取系统环境变量
19 os.path.abspath(path)  返回path规范化的绝对路径
20 os.path.split(path)  将path分割成目录和文件名二元组返回
21 os.path.dirname(path)  返回path的目录。其实就是os.path.split(path)的第一个元素
22 os.path.basename(path)  返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素
23 os.path.exists(path)  如果path存在,返回True;如果path不存在,返回False
24 os.path.isabs(path)  如果path是绝对路径,返回True
25 os.path.isfile(path)  如果path是一个存在的文件,返回True。否则返回False
26 os.path.isdir(path)  如果path是一个存在的目录,则返回True。否则返回False
27 os.path.join(path1[, path2[, ...]])  将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
28 os.path.getatime(path)  返回path所指向的文件或者目录的最后存取时间
29 os.path.getmtime(path)  返回path所指向的文件或者目录的最后修改时间
OS相关

 

print(os.getcwd()) #获取当前文件的工作目录
# E:\PycharmProjects\untitled\day27
os.chdir('E:\\PycharmProjects')
print(os.getcwd())
# E:\PycharmProjects

  

print(__file__) #获取当前文件的绝对路径
# E:/PycharmProjects/untitled/day27/sys_test.py
print(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'mod', '123.py'))
#E:\PycharmProjects\untitled\day27\mod\123.py 

sys模块

sys 是一个和 Python 解释器关系密切的标准库,它和帮助我们访问和 Python 解释器联系紧密的变量和函数

sys.argv           命令行参数List,第一个元素是程序本身路径
sys.exit(n)        退出程序,正常退出时exit(0)
sys.version        获取Python解释程序的版本信息
sys.path           返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
ys.platform       返回操作系统平台名称
import  sys,time
for i in range(9):
    sys.stdout.write('*')
    time.sleep(0.5)
进度条

Sys.argv[ ]其实就是一个列表,里边的项为用户输入的参数,关键就是要明白这参数是从程序外部输入的,而非代码本身的什么地方,要想看到它的效果就应该 将程序保存了,从外部来运行程序并给出参数

 

json、pickle、shelvel模块

序列化:把对象(变量)从内存中变成可存储或传输的过程称之为序列化

序列化作用:以某种存储形式使自定义对象持久化;跨平台数据交互

反序列化:把变量内容从序列化的对象重新读到内存里称之为反序列化

如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML,但更好的方法是序列化为JSON,因为JSON表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。JSON不仅是标准格式,并且比XML更快,而且可以直接在Web页面中读取,非常方便。

json

JSON (JavaScript Object Notation) 是一种轻量级的数据交换格式。

Python3 中可以使用 json 模块来对 JSON 数据进行编解码

  json.dumps(): 对数据进行编码。

  json.loads(): 对数据进行解码。

  无论数据是怎样创建的,只要满足json中的格式,就可以json.loads出来,不一定非要dumps的数据才能loads

  json.dumps()编码后的数据一定符合json中的数据规范

 

 

jsonh和eval对比

1 import json
2 
3 x = '[null, true, false, 1, 2]'
4 # res = eval(x) #报错,eval有局限性
5 # print(res)
6 print(json.loads(x)) #序列化成功

json与python

import json
dic = {'name':'alice', 'age':'18'}  #在json中--> {"name": "alice", "age": "18"} --> '{"name": "alice", "age": "18"}
i = 8 #--> '8'
h = 'hello' #-->"hello" --> ' "hello"'

s = json.dumps(h)
print(s)

 

如果你要处理的是文件而不是字符串,你可以使用 json.dump() 和 json.load() 来编码和解码JSON数据

import json
dic = {'name':'alice', 'age':'18'}
f = open('序列化对象','w')
json.dump(dic, f) #写入json数据
f.close()

with open('序列化对象', 'r') as f:
    data = json.load(f) #读取json数据
    # print(data)

pickle

 

 

 1 import pickle
 2  
 3 dic={'name':'alvin','age':23,'sex':'male'}
 4  
 5 print(type(dic))#<class 'dict'>
 6  
 7 j=pickle.dumps(dic)
 8 print(type(j))#<class 'bytes'>
 9  
10  
11 f=open('序列化对象_pickle','wb')#注意是w是写入str,wb是写入bytes,j是'bytes'
12 f.write(j)  #-------------------等价于pickle.dump(dic,f)
13  
14 f.close()
15 #-------------------------反序列化
16 import pickle
17 f=open('序列化对象_pickle','rb')
18  
19 data=pickle.loads(f.read())#  等价于data=pickle.load(f)
20  
21  
22 print(data['age'])

Pickle的问题和所有其他编程语言特有的序列化问题一样,就是它只能用于Python,并且可能不同版本的Python彼此都不兼容,因此,只能用Pickle保存那些不重要的数据,不能成功地反序列化也没关系。

 shelve

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

 1 import shelve
 2 
 3 f=shelve.open(r'sheve.txt') #返回类似字典的对象,可读可写
 4 print(type(f)) #<class 'shelve.DbfilenameShelf'>
 5 f['stu1_info']={'name':'egon','age':18,'hobby':['piao','smoking','drinking']}
 6 f['stu2_info']={'name':'gangdan','age':53}
 7 f['school_info']={'website':'http://www.pypy.org','city':'beijing'}
 8 
 9 print(f['stu1_info']['hobby'])
10 f.close()
View Code

 xml模块

xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单,不过,在json还没诞生的黑暗年代,大家只能选择用xml,至今很多传统公司如金融行业的很多系统的接口还主要是xml。

xml的格式如下,就是通过<>节点来区别数据结构的:

 1 <?xml version="1.0"?>
 2 <data>
 3     <country name="Liechtenstein">
 4         <rank updated="yes">2</rank>
 5         <year>2008</year>
 6         <gdppc>141100</gdppc>
 7         <neighbor name="Austria" direction="E"/>
 8         <neighbor name="Switzerland" direction="W"/>
 9     </country>
10     <country name="Singapore">
11         <rank updated="yes">5</rank>
12         <year>2011</year>
13         <gdppc>59900</gdppc>
14         <neighbor name="Malaysia" direction="N"/>
15     </country>
16     <country name="Panama">
17         <rank updated="yes">69</rank>
18         <year>2011</year>
19         <gdppc>13600</gdppc>
20         <neighbor name="Costa Rica" direction="W"/>
21         <neighbor name="Colombia" direction="E"/>
22     </country>
23 </data>
xml数据

xml协议在各个语言里的都 是支持的,在python中可以用以下模块操作xml:

 1 import xml.etree.ElementTree as ET
 2 
 3 tree = ET.parse("xmldata.xml") #parse分析,解析
 4 root = tree.getroot()
 5 print(root.tag)
 6 
 7 
 8 #遍历xml文档
 9 for child in root:
10     print(child.tag, child.attrib)
11     for i in child:
12         print(i.tag, i.text)
13 
14 
15 #只遍历指定节点 rank
16 for node in root.iter('rank'):
17     print(node.tag, node.text)
18 
19 
20 #修改
21 for node in root.iter('year'):
22     new_year = int(node.text) + 1
23     node.text = str(new_year)
24     node.set("new_attrib", "new_value") #添加新属性
25 
26 tree.write("abc.xml")
27 
28 
29 #删除node
30 for country in root.findall('country'):
31     rank = int(country.find('rank').text)
32     if rank > 50:
33         root.remove(country)
34 
35 tree.write('output.xml')
xml模块

自己创建xml文档:

 1 import xml.etree.ElementTree as ET
 2  
 3  
 4 new_xml = ET.Element("namelist")
 5 name = ET.SubElement(new_xml,"name",attrib={"enrolled":"yes"})
 6 age = ET.SubElement(name,"age",attrib={"checked":"no"})
 7 sex = ET.SubElement(name,"sex")
 8 sex.text = '33'
 9 name2 = ET.SubElement(new_xml,"name",attrib={"enrolled":"no"})
10 age = ET.SubElement(name2,"age")
11 age.text = '19'
12  
13 et = ET.ElementTree(new_xml) #生成文档对象
14 et.write("test.xml", encoding="utf-8",xml_declaration=True)
15  
16 ET.dump(new_xml) #打印生成的格式
创建xml文档

re模块

正则表达式(或 RE)是一种小型的、高度专业化的编程语言,(在Python中)它内嵌在Python中,并通过 re 模块实现。正则表达式模式被编译成一系列的字节码,然后由用 C 编写的匹配引擎执行。

常用于字符串的模糊匹配(普通字符、元字符):

  普通字符:

  元字符:. * ^ $  ? + {}  []  |  ()  \ 

元字符之 . * ^ $ ? +  {}

  . * + > {} 常用于指出被匹配(如\d,‘e'这个字母)的字符个数

  .  匹配除  \n 之外的任何单个字符

  * 可以表示任意个数字符

  + 代表至少一个字符

  ?指代0或1个字符,惰性匹配

  {n} 指代n个字符,{n,m} 指代n~m个字符

  美元符号 $ 表示字符结束   \d$ 表示必须以数字结尾

  ^ 表示字符开头   ^\d表示必须以数字开头 

import re

# . 匹配除 \n 之外的单个字符
print(re.findall('h.', 'hello,wrold. he can be the best.hurry up'))
# ['he', 'he', 'he', 'hu']
# 匹配 h 后面跟一个字符

print(re.findall('h...', 'hello,wrold. he can be the best'))
# ['hell', 'he c', 'he b']
# h 后面跟 3 个字符


# * 可以匹配任意个数字符 [0,+∞]贪婪匹配
print(re.findall('he*', 'hello,wrold.hee can be thee2 besth'))
# ['he', 'hee', 'hee', 'h']
# h后面的跟着字母e, 且字母e出现的次数可以是零次或无穷大次

ret = re.findall('py*', 'pyythonpyyyy')
print(ret)  # ['pyy', 'pyyyy']

ret = re.findall('py*n', 'pyythonpyyyy')
print(ret)  # []

ret = re.findall('py.*n', 'pyythonpyyyy')
print(ret)  # ['pyython']


# + 可以匹配至少一个字符 [1,+∞] 贪婪匹配
res = re.findall('he+', 'hello,wrold. he can be the best.hurry up')
print(res) # ['he', 'he', 'he']


# ? 可以匹配 0 或 1 个字符 非贪婪匹配
res = re.findall('he?', 'heello,wrold. hie')
print(res) # ['he', 'h']


# ^ 表示字符开头, $ 表示字符结尾
res = re.findall('^he.*up$', 'hello,wrold. he can be the best.hurry up')
print(res) # ['hello,wrold. he can be the best.hurry up']

res = re.findall('^he.*u$', 'hello,wrold. he can be the best.hurry up')
print(res) # []


# {n} 指代n个字符,{n,m} 指代 n~m个字符
res = re.findall('he{3}', 'hello,wrold. hee can be theee best.hurry up')
print(res) # ['heee']
res = re.findall('he{0,3}', 'hello,wrold. hee can be theee best.hurry up') #贪婪匹配
print(res) # ['he', 'hee', 'heee', 'h']

  

 注意:前面的 *,+,等都是贪婪匹配,也就是尽可能匹配,后面加?号使其变成惰性匹配

ret=re.findall('abc*?','abcccccc')
print(ret)#['ab']

元字符之字符集 []

在字符集里有功能的符号:  -  ^  \

  [Pp]ython 可以匹配到 python Python

  [aeiou] 可以匹配到括号内任一字母

  ’py.'  可以匹配 'pyc' 'pyo' 'py!'等

import re

ret = re.findall('[pP]ython', 'python and Python')
print(ret)  # ['python', 'Python']

# 在字符集只有这三个符号有有功能: - ^ \ 其他的视为普通字符
# -
ret = re.findall('[a-z]', 're666')
print(ret)  # ['r', 'e']

ret = re.findall('[1-9]', '45dha3')
print(ret)  # ['4', '5', '3']

# ^ 表示取反
ret = re.findall('[^ah]', '45bdha3')
print(ret)  # ['4', '5', 'b', 'd', '3']

# \ 转义符
ret = re.findall('[\d]', '45bdha3')
print(ret)  # ['4', '5', '3']

# 除了 ^ - \ 都视为普通字符
ret = re.findall('[.+]', 'a.cd+')
print(ret)  # ['.', '+']

元字符之转义符 \

匹配特殊字符(如’-‘),在正则中用 \ 转义 

  \d 匹配一个数字 [0,9]

  \D 匹配一个非数字字符[^0-9]

  \s 匹配任意个空白字符 [\f \n \r \r \v]

  \S 匹配任意个非空白字符 [^\f \n \r \r \v]

  \w 匹配字母数字字符 [A-Z a-z 0-9]

  \W 匹配非字母数字字符[^A-Z a-z0-9]

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

import re

print(re.findall('\d', 'saf3sdf54')) #['3', '5', '4']
print(re.findall('\D', 'saf3sdf54')) #['s', 'a', 'f', 's', 'd', 'f']

print(re.findall('\s', 'I am the best')) #[' ', ' ', ' ']
print(re.findall('\S', 'I am the best')) #['I', 'a', 'm', 't', 'h', 'e', 'b', 'e', 's', 't']

# 注意
print(re.findall('I\b', 'I am the best')) #[]
print(re.findall('I\\b', 'I am the best')) # ['I']
print(re.findall(r'I\b', 'I am the best')) # ['I']

正则中,用转义符 \ 将字母 b 转为特殊字符边界的意思。所以 \b 表示匹配一个特殊字符边界;

python解释器中 \ 也是转义符,\b 转义为 “退格键 backspace”的意思,' I\b '会被pytho解释为 'I退格键' 的意思,

要么使用 r 取消python的转义,要么使用 \ 将 \b 中的 \ 转为普通字符'\'
r --> rowstring原生字符串,也就是在python中的 \ 没有转义作用 

元字符之分组()

() 内的作为一组进行匹配,分组内的会默认优先显示

import re

print(re.findall('ad+', 'addd')) # ['addd']
print(re.findall('(ad)+', 'addd')) # ['ad']

ret = re.search('.*', 'alice23')
print(ret.group()) # alice23

# 分组中的内容优先显示
print(re.findall('abc', 'abcabcabc')) #['abc', 'abc', 'abc']
print(re.findall('(abc)+', 'abcabcabc')) #['abc']
print(re.findall('(?:abc)+', 'abcabcabc')) #['abcabcabc']

# 设置分组的组名
ret = re.search('(?P<name>\D{5})(?P<age>\d{2})', 'alice23')
print(ret.group()) #alice23
print(ret.group('name')) #alice
print(ret.group('age')) #23 

元字符之 |

| 在正则表达式中表示或的逻辑

import re

print(re.search('(ab)|\d', 'sasbd23'))
#<re.Match object; span=(5, 6), match='2'>

print(re.search('(ab)|\d+', 'sasbd23'))
#<re.Match object; span=(5, 7), match='23'>

re模块常用方法

import re

# re.findall(string[, pos[, endpos]])
# 在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。
print(re.findall('a', 'alice apple')) #['a', 'a']

# 注意:findall会优先返回组里的匹配结果,可以取消这个权限
ret = re.findall('www\.(baidu|sougou)\.com', '2354www.baidu.comdcvbe')
print(ret) #['baidu']
ret = re.findall('www\.(?:baidu|sougou)\.com', '2354www.baidu.comdcvbe')
print(ret) #['www.baidu.com']


# re.search(pattern, string, flags=0)
# 函数会在字符串内查找模式匹配,只到找到第一个匹配然后返回一个包含匹配信息的对象,
# 该对象可以通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。
print(re.search('a', 'alice apple')) #<re.Match object; span=(0, 1), match='a'>
print(re.search('a', 'alice apple').group()) #a


# re.match与re.search相似,但是只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None
print(re.match('a','liace')) #None


# split方法按照能够匹配的子串将字符串分割后返回列表
print(re.split(' ', 'I am the best')) #['I', 'am', 'the', 'best']
print(re.split('a', 'bac')) #['b', 'c']
print(re.split('a', 'abc')) #['', 'bc']
print(re.split('a', 'abac')) #['', 'b', 'c']
print(re.split('[ab]', 'abcd' )) #['', '', 'cd']  先按'a'分割得到''和'bcd',在对''和'bcd'分别按'b'分割


# sub方法用于替换字符串中的匹配项
phone = '2004-888-999 # 这是一个电话号'
print(re.sub('#.*', '', phone)) #2004-888-999
print(re.sub('\D', '', phone)) #2004888999

# compile函数用于编译正则表达式,生成一个正则表达式(Pattern)对象,供match()和search()这两个函数使用
# 如果该正则表达式使用频率较高,建议使用compile
com = re.compile('\d{3}')
ret = com.search('sagfds2334fdsg')
print(ret) #<re.Match object; span=(6, 9), match='233'>
print(ret.group()) #233


# finditer和findall类似,在字符串中找到正则表达式所匹配的所有子串,但是返回一个迭代器对象
x = re.finditer('\d+', '32dd435ff435gg345')
print(x) #<callable_iterator object at 0x004FBEB0>
print(x.__next__()) # <re.Match object; span=(0, 2), match='32'>
print(next(x).group()) #435

logging模块

简单应用

import logging

logging.debug('this can write message about debug')
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critial message')

# 执行结果:
# WARNING:root:warning message
# ERROR:root:error message
# CRITICAL:root:critial message

  默认情况下,pytho的logging模块将日志打印到了标准输出中,且只显示了大于等于WARNING级别的日志,这说明默认的日志级别设置为WARNING(日志级别等级CRITICAL > ERROR > WARNING > INFO > DEBUG > NOTSET),默认的日志格式为日志级别:Logger名称:用户输出消息。

  只有日志等级大于或等于设置的日志级别的日志才会被输出

日志的基本设置

import logging

logging.basicConfig(
    level = logging.DEBUG,
    filename = 'logtest.log',
    # filename:用指定的文件名创建FiledHandler,这样日志会被存储在指定的文件中
    filemode = 'w',
    format = '%(asctime)s %(filename)s [%(lineno)d] %(message)s',
    # %(filename)s 调用日志输出函数的模块的文件名

)

logging.debug('this can write message about debug')
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critial message')
1 2019-10-01 14:47:38,255 logging07.py [29] this can write message about debug
2 2019-10-01 14:47:38,255 logging07.py [30] info message
3 2019-10-01 14:47:38,255 logging07.py [31] warning message
4 2019-10-01 14:47:38,255 logging07.py [32] error message
5 2019-10-01 14:47:38,255 logging07.py [33] critial message
logtest1.log文件

由此可见在logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为:

  filename:用指定的文件名创建FiledHandler,这样日志会被存储在指定的文件中。

  filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。

  format:指定handler使用的日志显示格式。

  datefmt:指定日期时间格式。 

  level:设置rootlogger(后边会讲解具体概念)的日志级别

  stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件(f=open('test.log','w')),默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略。

 1 %(name)s Logger的名字
 2 %(levelno)s 数字形式的日志级别
 3 %(levelname)s 文本形式的日志级别
 4 %(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
 5 %(filename)s 调用日志输出函数的模块的文件名
 6 %(module)s 调用日志输出函数的模块名
 7 %(funcName)s 调用日志输出函数的函数名
 8 %(lineno)d 调用日志输出函数的语句所在的代码行
 9 %(created)f 当前时间,用UNIX标准的表示时间的浮 点数表示
10 %(relativeCreated)d 输出日志信息时的,自Logger创建以 来的毫秒数
11 %(asctime)s 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
12 %(thread)d 线程ID。可能没有
13 %(threadName)s 线程名。可能没有
14 %(process)d 进程ID。可能没有
15 %(message)s用户输出的消息
format参数中可能用到的格式串

logger对象

logging库提供了多个组件:Logger、Handler、Filter、Formatter。

其中Logger对象提供应用程序可直接使用的接口,Handler发送日志到适当的目的地,Filter提供了过滤日志信息的方法,Formatter指定日志显示格式。

import logging

logger = logging.getLogger() #返回一个logger对象,如果没有指定名字将返回root logger

# 用于将日志写入文件
fh = logging.FileHandler('logtest2.log')
# 用于将日志输出到控制台
ch = logging.StreamHandler()

formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

fh.setFormatter(formatter)
ch.setFormatter(formatter)

logger.addHandler(fh) #logger添加fh的功能
logger.addHandler(ch) #logger添加ch的功能更

logger.setLevel(logging.WARNING) #设置日志的输出级别

logger.debug('this can write message about debug')
logger.info('info message')
logger.warning('warning message')
logger.error('error message')
logger.critical('critial message')

  注意:

  logger1 = logging.getLogger('logger1')创建了root Logger的孩子(root.)logger1,而孩子,孙子,重孙……既会将消息分发给他的handler进行处理也会传递给所有的祖先Logger处理。

import logging

logger = logging.getLogger()
logger1 = logging.getLogger('logger1')

# 用于输出到文件
fh = logging.FileHandler('logtest3.log')
# 再创建一个handler,用于输出到控制台
ch = logging.StreamHandler()

formatter = logging.Formatter('%(lineno)d-%(asctime)s - %(name)s - %(levelname)s - %(message)s')

fh.setFormatter(formatter)
ch.setFormatter(formatter)

logger.addHandler(fh) #logger对象可以添加多个fh和ch对象
logger.addHandler(ch)
logger1.addHandler(fh)
logger1.addHandler(ch)

logger1.setLevel(logging.DEBUG)

logger.debug('logger1 debug message')
logger.info('logger1 info message')
logger.warning('logger1 warning message')
logger.error('logger1 error message')
logger.critical('logger1 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')
代码
 1 25-2019-10-01 15:17:24,406 - root - WARNING - logger1 warning message
 2 26-2019-10-01 15:17:24,407 - root - ERROR - logger1 error message
 3 27-2019-10-01 15:17:24,407 - root - CRITICAL - logger1 critical message
 4 29-2019-10-01 15:17:24,407 - logger1 - DEBUG - logger1 debug message
 5 29-2019-10-01 15:17:24,407 - logger1 - DEBUG - logger1 debug message
 6 30-2019-10-01 15:17:24,407 - logger1 - INFO - logger1 info message
 7 30-2019-10-01 15:17:24,407 - logger1 - INFO - logger1 info message
 8 31-2019-10-01 15:17:24,407 - logger1 - WARNING - logger1 warning message
 9 31-2019-10-01 15:17:24,407 - logger1 - WARNING - logger1 warning message
10 32-2019-10-01 15:17:24,407 - logger1 - ERROR - logger1 error message
11 32-2019-10-01 15:17:24,407 - logger1 - ERROR - logger1 error message
12 33-2019-10-01 15:17:24,408 - logger1 - CRITICAL - logger1 critical message
13 33-2019-10-01 15:17:24,408 - logger1 - CRITICAL - logger1 critical message
控制台中的结果

configparser模块

这个模块常用于操作配置文件

[DEFAULT]
ServerAliveInterval = 45
Compression = yes
CompressionLevel = 9
ForwardX11 = yes
  
[bitbucket.org]
User = hg
  
[topsecret.server.com]
Port = 50022
ForwardX11 = no
配置文档
 1 import configparser
 2   
 3 config = configparser.ConfigParser()
 4 config["DEFAULT"] = {'ServerAliveInterval': '45',
 5                       'Compression': 'yes',
 6                      'CompressionLevel': '9'}
 7   
 8 config['bitbucket.org'] = {}
 9 config['bitbucket.org']['User'] = 'hg'
10 config['topsecret.server.com'] = {}
11 topsecret = config['topsecret.server.com']
12 topsecret['Host Port'] = '50022'     # mutates the parser
13 topsecret['ForwardX11'] = 'no'  # same here
14 config['DEFAULT']['ForwardX11'] = 'yes'<br>
15 with open('example.ini', 'w') as f:
16    config.write(f)
生成配置文档
 1 import configparser
 2 
 3 config = configparser.ConfigParser()
 4 
 5 #---------------------------------------------查
 6 print(config.sections())   #[]
 7 
 8 config.read('example.ini')
 9 
10 print(config.sections())   #['bitbucket.org', 'topsecret.server.com']
11 
12 print('bytebong.com' in config)# False
13 
14 print(config['bitbucket.org']['User']) # hg
15 
16 print(config['DEFAULT']['Compression']) #yes
17 
18 print(config['topsecret.server.com']['ForwardX11'])  #no
19 
20 
21 for key in config['bitbucket.org']:
22     print(key)
23 
24 
25 # user
26 # serveraliveinterval
27 # compression
28 # compressionlevel
29 # forwardx11
30 
31 
32 print(config.options('bitbucket.org'))#['user', 'serveraliveinterval', 'compression', 'compressionlevel', 'forwardx11']
33 print(config.items('bitbucket.org'))  #[('serveraliveinterval', '45'), ('compression', 'yes'), ('compressionlevel', '9'), ('forwardx11', 'yes'), ('user', 'hg')]
34 
35 print(config.get('bitbucket.org','compression'))#yes
36 
37 
38 #---------------------------------------------删,改,增(config.write(open('i.cfg', "w")))
39 
40 
41 config.add_section('yuan')
42 
43 config.remove_section('topsecret.server.com')
44 config.remove_option('bitbucket.org','user')
45 
46 config.set('bitbucket.org','k1','11111')
47 
48 config.write(open('i.cfg', "w"))
增删改查

hashlib模块

该模块用于加密相关的操作

了解hash:

  hash是一种算法(3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法),该算法接受传入的内容,经过运算得到一串hash值

特点:

  只要传入的内容一样,得到的hash值必然一样=====>常在使用明文传输密码文件时进行完整性校验

  不能由hash值返解成内容=======》把密码做成hash值,不应该在网络传输明文密码

  只要使用的hash算法不变,无论校验的内容有多大,得到的hash值长度是固定的

常用方法:

import hashlib

x = hashlib.md5() #选择加密的算法
# x = hashlib.sha256()

x.update('admin'.encode('utf-8'))
print(x.hexdigest()) #21232f297a57a5a743894a0e4a801fc3

x.update('hello'.encode('utf-8'))
print(x.hexdigest()) #d1d317984f2b77f0e3dbe22bd36d61a7


y = hashlib.md5()
y.update('admin'.encode('utf-8'))
y.update('hello'.encode('utf-8'))
print(y.hexdigest()) #d1d317984f2b77f0e3dbe22bd36d61a7
# 把一段很长的数据update多次,与一次update这段长数据,得到的结果一样
# 但是update多次为校验大文件提供了可能。

加密算法虽然依然非常厉害,但时候存在缺陷,即:通过撞库可以反解。所以,有必要对加密算法中添加自定义key再来做加密。 

  撞库:将常用的字符如admin、root的明文和密文保存起来,然后根据密文进行比对,就可以反解,得到明文

  防止撞库:用户的密码前添加自定义明文的密文

# 防止撞库
z = hashlib.md5()
z.update('admin'.encode('utf-8'))
z.update('611'.encode('utf-8'))
print(z.hexdigest()) #3a1057fb2bfdfd79212b4dfa6d0aa2e9
 1 import hashlib
 2 passwds=[
 3     'alex3714',
 4     'alex1313',
 5     'alex94139413',
 6     'alex123456',
 7     '123456alex',
 8     'a123lex',
 9     ]
10 def make_passwd_dic(passwds):
11     dic={}
12     for passwd in passwds:
13         m=hashlib.md5()
14         m.update(passwd.encode('utf-8'))
15         dic[passwd]=m.hexdigest()
16     return dic
17 
18 def break_code(cryptograph,passwd_dic):
19     for k,v in passwd_dic.items():
20         if v == cryptograph:
21             print('密码是===>\033[46m%s\033[0m' %k)
22 
23 cryptograph='aee949757a2e698417463d47acac93df'
24 break_code(cryptograph,make_passwd_dic(passwds))
模拟撞库破解密码

 

参考

https://www.cnblogs.com/linhaifeng/p/7278389.html

https://www.cnblogs.com/yuanchenqi/articles/5732581.html

https://www.runoob.com/python/python-modules.html

posted @ 2019-09-28 17:02  西伯利亚狼dreamer  阅读(439)  评论(0编辑  收藏  举报