python初识day5

本节内容:

  • 模块介绍
  • 模块的导入和使用
  • 常用模块一
    • time&datetime模块
    • random模块
    • os模块
    • sys模块
    • 序列化模块
    • re模块
  • 常用模块二
    • hashlib模块
    • configpares模块 
    • logging模块

一、模块介绍


 什么是模块?

通俗来说:一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀。 

 但其实import'加载的模块分为四个通用类别:

  1. 使用python编写的代码(.py文件)
  2. 已被编译为共享库或DLL的C或C++扩展
  3. 包好一组模块的包
  4. 使用C编写并链接到python解释器的内置模块

为何要使用模块?

如果你退出python解释器然后重新进入,那么你之前定义的函数或者变量都将丢失,因此我们通常将程序写道文件中以便永久保存下来,需要时就通过python test.py方式去执行,此时test.py被称为脚本script.

随着程序的发展,功能越来越多,为了方便管理,我们通常将程序分成一个个的文件,这样做程序的结构更清晰,方便管理。这时我们不仅仅可以把这些文件当做脚本去执行,还可以把他们当做模块来导入到其他的模块中,实现了功能的重复利用。

二、模块的导入和使用


import

自定义了一个名叫haha.py的模块,模块内容如下:

#haha.py

print("haha")
aha= 520
def a():
  print("aaa")

def b():
  print("bbb")

def c():
  global aha
  aha = 0

知识点一、模块可以包含可执行的语句和函数的定义,这些语句的目的是初始化模块,它们只在模块名第一次遇到导入import语句时才执行(import语句是可以在程序中的任意位置使用的,且针对同一个模块很import多次,为了防止你重复导入,python的优化手段是:第一次导入后就将模块名加载到内存了,后续的import语句仅是对已经加载大内存中的模块对象增加了一次引用,不会重新执行模块内的语句),如下 

#lala.py

import haha.py 
#只在第一次导入时才执行my_module.py内代码,此处的显式效果是只打印一次'from the my_module.py',当然其他的顶级代码也都被执行了,只不过没有显示效果.


import haha.py
import haha.py

#执行结果
#haha

 我们可以从sys.modules中找到已经加载的模块,sys.modules是一个字典,内部包含模块名与模块对象的映射,该字典 决定了导入模块时是否需要重洗导入。

知识点二、每个模块都是一个独立的命名空间,定义这个模块中的函数,把这个模块的名称空间当作全局名称空间,这样我们在编写自己的模块时,就不用担心我们定义在自己模块中全局变量会在被导入时,与使用者的全局变量冲突。

 1 #测试一:aha与haha.aha不冲突
 2 #lala.py
 3 
 4 import haha
 5 
 6 aha = 521
 7 print(aha)
 8 print(haha.aha)
 9 
10 #输出:
11 521
12 520
#测试一:aha与haha.aha不冲突
 1 #测试二、aaa()与haha.aaa()不冲突
 2 #lala.py
 3 
 4 import haha
 5 
 6 def aaa():
 7     print("aaa1")
 8     
 9 haha.aaa()
10 aaa()
11 #输出
12 
13 haha
14 aaa
15 aaa1
测试二、函数名不冲突
 1 #测试三、执行haha.ccc()操作的全局变量aha仍然是haha中的
 2 #lala.py
 3 
 4 import haha
 5 
 6 aha = 521
 7 haha.ccc()
 8 
 9 print(aha)
10 print(haha.aha)
11 
12 #输出
13 haha
14 521
15 0
测试三、执行haha.ccc()操作的全局变量aha仍然是haha中的

 小总结:首次导入模块haha.py时会做三件事:

1.为源文件(haha.py模块)创建新的命名空间,在haha.py中定义的函数和方法若是使用到global时访问的就是这个命名空间。

2.在新创建的命名空间中执行模块中包含的代码,见初始导入import  haha

提示:导入模块时到底执行了什么?

事实上函数定义也是“被执行”的语句,模块级别函数定义的执行将函数名放入模块全局名称空间表,用globals()可以查看

  3.创建名字haha来引用该命名空间

 这个名字和变量名没什么区别,都是‘测试一’的,且使用haha.名字的方式可以访问haha.py文件中的名字,haha.名字与lala.py中的名字来源于两个完全不同的地方。

 知识点四:为模块起别名,相当于m1=1;m2=m1

import haha as shasha

print(shasha.aha) == print(haha.aha)

 例子一:有两个sql模块mysql和oralce,根据用户的输入,选择不同的sql功能

#mysql.py

def sqlparse():

  print("from myaql sqlparse")

#oracle.py

def sqlparse():

  print("from oracle sq;parse")

 

#text.py

db_type = input(">>>:")

if db_type == "mysql"

  import mysql as db

elif db_type == "oracle"

  import oracle as db

 

db.sqlparse()

例子二:为已经导入的模块起别名的方式对编写可扩展的代码很有用,假设有两个模块xmlreader.py和csreader.py,它们都定义了函数read_data(filename):用来从文件中读取一些数据,但是采用不同的输入格式。可以编写代码来选择性的挑选读取模块

if file_format == "xml"

  import xmlreader as reader

elif file_format == "csv"

  import csvreader as reader

data = reader.read_data(filename)

知识点五几种别的导入方式

import module  #上边详细解释的方式

from module.xx.xx import xx 
from module.xx.xx import xx as rename  
from module.xx.xx import *

常用模块一:


time & datetime模块

 1 import time
 2 print(time.time()) #返回当前时间的时间戳(1970纪元后经过的浮点秒数)(格林尼治时间)。
 3 print(type(time.time()))
 4 print("-----------------------------------")
 5 print(time.localtime())#作用是格式化时间戳为本地的时间(时间元组)
 6 print(type(time.localtime()))
 7 # 不输入参数,返回本地时间,(本时区)
 8 #  如果sec参数未输入,则以当前时间为转换标准。
 9 print("-----------------------------------")
10 print('时间戳,转换为元组')
11 t = 0.0
12 t1 = time.localtime(t)#不带参数就是现在的时间
13 print('时间localtime,本地时间', t1)
14 t1 = time.gmtime(t)
15 print('时间gmtime,格林尼治时间', t1)
16 print(type(t1))
17 print('----------------------------------')
18 print('分两步,1:时间戳转时间元组,2:时间元组转字符串')
19 t = 0.0
20 t1 = time.localtime(t)
21 t2 = time.strftime('%Y-%m-%d %H:%M:%S', t1)
22 print(t2)
23 print('----------------------------------')
24 print('元组,转为时间字符串')
25 t = (1970, 1, 1, 8, 0, 0, 0, 0, 0)
26 t1 = time.strftime('%Y-%m-%d %H:%M:%S', t)
27 #把元组按照格式变成时间字符串
28 t2 = time.strftime('%Y-%m-%d %H:%M:%S')
29 #没有t这个参数时就默认当前时间的元组
30 print(t1)
31 print(t2)
32 print('----------')
33 print('----------------------------------')
34 t0 = time.clock()
35 # t0 = time.clock()  # 第一次调用time.clock,标记一个时间为0.0
36 time.sleep(2)
37 t1 = time.clock()
38 # 第二次调用,从第一个time.clock开始到现在的时间
39 time.sleep(2)
40 t2 = time.clock()
41 # 第三次调用,从第一个time.clock开始到现在的时间
42 
43 print(t0)
44 print(t1)
45 print(t2)
46 print(t1 - t0)
47 print(t2 - t1)
48 print(t2 - t0)
49 #以下字符串方便用来存记录,
50 now_time = time.strftime('%Y-%m-%d %H:%M:%S')  # 20171123093804  当前时间
51 print(now_time)
52 print(type(now_time))  # 格式是字符串
53 print('----------')
54 now=str(datetime.datetime.now())
55 print(now)
56 print(type(now))    #格式是字符串 带毫秒的
57 print('----------')
58 today = time.strftime('%Y%m%d')  # 20171123 当前日期
59 print(today)
60 print(type(today))  # 格式是字符串
61 print('----------')

radom模块

1、定义

随机数模块

2、random.random()方法

随机返回一个0-1之间的浮点数,且这个数不会大于1

import random

print(random.random())

 3、random.randint(a, b)

生成[a,b]之间一个任意的随机数(包含a, b)

import random

print(random.randint(1, 10))

4、random.randrage(a, b)

生成(a,b)之间一个任意的随机数(不包含a, b)

import random

print(random.randerage(a, b))

5、random.choice([])/(())

.chioce()中可以放一个数组,列表,字符串。输出结果是随机选出一个元素。

import random

print(random.choice([1, 2, 3, 4]))

6、random.sample([],n)

在列表中取出n个元素

import random

print(random.sample(1, 2, 3, 4 ,5 ,6),3)#在元组(1, 2, 3, 4 ,5 ,6)中取出3和任意元素。

7、random.uniform(a, b)

取出a, b 之间的一个随机浮点数

import random

print(random.uniform(a,b))

8、random.shuffle()

打乱次序

import random

l = [1, 2, 3, 4]

random.shuffe(l)

print(l)  #得到打乱顺序后的l

os模块

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

 sys模块

1 sys.argv           命令行参数List,第一个元素是程序本身路径
2 sys.exit(n)        退出程序,正常退出时exit(0)
3 sys.version        获取Python解释程序的版本信息
4 sys.maxint         最大的Int值
5 sys.path           返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
6 sys.platform       返回操作系统平台名称
7 sys.stdout.write('please:')
8 val = sys.stdin.readline()[:-1]

序列化模块

用于序列的模块有两个:

  • json,用于字符串和python数据类型间进行转换
  • pickle,用于python特有的类型和python的数据类型间的转换

josn模块提供了四个功能:dumps、dump、loads、load

pickle模块提供了四个功能:dumps、dump、loads、load

1.json——dumps&dump

dumps:序列化——将字典形式的数据类型转化为字符串类型

1 import json
2 data = {"a": 11133, "b": 222}
3 print(data, type(data))
4 data = json.dumps(data)
5 print(data, type(data))
6 
7 #输出
8 {'a': 11133, 'b': 222} <class 'dict'>
9 {"a": 11133, "b": 222} <class 'str'>
json.dumps

dump:接收一个文件的句柄,直接将字典转换为json字符串写入文件

import json
data = {"a": 111, "b": 222}
f = open("zhuzhu", "w")
json.dump(data, f)

#输出
建立了新的名为“zhuzhu”的.text文件,以json格式将data存到“huzhu.text里
json.dump

2.json——loads&load

 loads:反序列化,将一个字符串格式的字典转换成一个字典

 1 import json
 2 data = {'a': 111, 'b': 222}
 3 data = json.dumps(data)
 4 print(data, type(data))
 5 str = json.loads(data)
 6 print(str, type(str))
 7 
 8 #输出
 9 {"a": 111, "b": 222} <class 'str'>
10 {'a': 111, 'b': 222} <class 'dict'>
loads

 load:接收一个文件句柄,直接将文件中的json字符串转换成数据结构返回

import json
# data = '''{"aaa1": 111, "bbb2": 222}'''
f = open("zhuzhu", "r")
str = json.load(f)
print(str, type(str))

#输出
{'aaa1': 111, 'bbb2': 222} <class 'dict'>
View Code

3.pickle————dumps&dump

 1 import pickle
 2 
 3 data = {"k1": 123, "k2": "hello"}
 4 
 5 #pickle.dumps  将数据通过特殊形式转换为只有python语言认识的字符串
 6 p_str = pickle.dumps(data)
 7 print(p_str)
 8 
 9 #pickle.dump  将数据通过特殊的形式转换为只有python语言认识的字符串,并写入文件
10 with open("D:/result.pk", "w") as fp:
11     pickle.dump(data,fp)

 re模块

1.普通字符和11个元字符:

普通字符
匹配自身
abc
abc
.
匹配任意除换行符"\n"外的字符(在DOTALL模式中也能匹配换行符
a.c
abc
\
转义字符,使后一个字符改变原来的意思
a\.c;a\\c
a.c;a\c
*
匹配前一个字符0或多次
abc*
ab;abccc
+
匹配前一个字符1次或无限次
abc+
abc;abccc
?
匹配一个字符0次或1次
abc?
ab;abc
^
匹配字符串开头。在多行模式中匹配每一行的开头 ^abc
abc
$
匹配字符串末尾,在多行模式中匹配每一行的末尾 abc$
abc
| 或。匹配|左右表达式任意一个,从左到右匹配,如果|没有包括在()中,则它的范围是整个正则表达式
abc|def
abc
def
{} {m}匹配前一个字符m次,{m,n}匹配前一个字符m至n次,若省略n,则匹配m至无限次
ab{1,2}c
abc
abbc
[]
字符集。对应的位置可以是字符集中任意字符。字符集中的字符可以逐个列出,也可以给出范围,如[abc]或[a-c]。[^abc]表示取反,即非abc。
所有特殊字符在字符集中都失去其原有的特殊含义。用\反斜杠转义恢复特殊字符的特殊含义。
a[bcd]e
abe
ace
ade
 
()
被括起来的表达式将作为分组,从表达式左边开始没遇到一个分组的左括号“(”,编号+1.
分组表达式作为一个整体,可以后接数量词。表达式中的|仅在该组中有效。
(abc){2}
a(123|456)c
abcabc
a456c

 这里需要强调以下反斜杠\的作用:

  •  反斜杠后边跟元字符去除特殊功能;(即将特殊字符转义成普通字符)
  • 反斜杠后边跟普通字符实现特殊功能;(即预定义字符)
  • 引用序号对应的字组所匹配的字符串。
1 a = re.search(r'(tina)(fei)haha\2','tinafeihahafei tinafeihahatina').group()
2 print(a)
3 结果:
4 tinafeihahafei

2.预定义的字符集(可以写在字符集[...]中)

\d
数字:[0-9]
a\bc
a1c
\D
非数字:[^\d]
a\Dc
abc
\s
匹配任何空白字符:[<空格>\t\r\n\f\v]
a\sc
a c
\S 非空白字符:[^\s]
a\Sc
abc
\w
匹配包括下划线在内的任何字字符:[A-Za-z0-9_]
a\wc
abc
\W
匹配非字母字符,即匹配特殊字符
a\Wc
a c
\A
仅匹配字符串开头,同^ \Aabc
abc
\Z
仅匹配字符串结尾,同$
abc\Z
abc
\b
匹配\w和\W之间,即匹配单词边界匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。 \babc\b
a\b!bc
空格abc空格
a!bc
\B
[^\b]
a\Bbc
abc

3.特殊分组用法:

(?P<name>)
分组,除了原有的编号外再指定一个额外的别名 (?P<id>abc){2}
abcabc
(?P=name)
引用别名为<name>的分组匹配到字符串 (?P<id>\d)abc(?P=id)
1abc1
5abc5
\<number>
引用编号为<number>的分组匹配到字符串 (\d)abc\1
1abc1
5abc5

 4.re模块中常用功能函数

compile()

编写正则表达式时,返回一个对象模式。

格式:re.compile(pattern, flags = 0)

  pattern:编译时用的表达式字符串。

  flags:编译标志位,用于修改正则表达式的匹配方式,如:是否区分大小写,多行匹配等。常用的flags有:

标志
含义
re.S(DOTALL)
使.匹配包括换行在内的所有字符
re.I(IGNORECASE)
使匹配对大小写不敏感
re.L(LOCALE)
做本地化识别(locale-aware)匹配,法语等
re.M(MULTILINE)
多行匹配,影响^和$
re.X(VERBOSE)
该标志通过给予更灵活的格式以便将正则表达式写得更易于理解
re.U
根据Unicode字符集解析字符,这个标志影响\w,\W,\b,\B
1 import re
2 tt = "Tina is a gggoooddd girl, she is cool, clever, and so on...GgoOOL"
3 rr = re.compile('\w*oo\w*')
4 print(rr.findall(tt))   #查找所有包含'oo'的单词
5 
6 #输出:
7 ['gggoooddd', 'cool']
例子
match()

re.match( )方法匹配的是以xxx开头的字符串,若不是开头的,尽管属于str内,则无法匹配。

格式:

re.match(pattern,string,flags=0)

1 print(re.match('com','comwww.runcomoob').group())
2 print(re.match('com','Comwww.runcomoob',re.I).group())
3 执行结果如下:
4 com
5 com
例子

search()

格式:

re.search(pattern,string,flags=0)

若string中包含了pattern子串,则返回match对象,否则返回None,如果string中存在多个pattern字串,只返回第一个。

1 print(re.search('\dcom','www.4comrunoob.5com').group())
2 
3 #输出
4 4com
例子

*注:match和search一旦匹配成功,就是一个match object对象,而match object对象有以下几个方法:

  • group() 返回被 RE 匹配的字符串
  • start() 返回匹配开始的位置
  • end() 返回匹配结束的位置
  • span() 返回一个元组包含匹配 (开始,结束) 的位置
  • group() 返回re整体匹配的字符串,可以一次输入多个组号,对应组号匹配的字符串。

a. group()返回re整体匹配的字符串,
b. group (n,m) 返回组号为n,m所匹配的字符串,如果组号不存在,则返回indexError异常
c.groups()groups() 方法返回一个包含正则表达式中所有小组字符串的元组,从 1 到所含的小组号,通常groups()不需要参数,返回一个元组,元组中的元就是正则表达式中定义的组。

1 import re
2 a = "123abc456"
3  print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(0))   #123abc456,返回整体
4  print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(1))   #123
5  print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(2))   #abc
6  print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(3))   #456
7 ###group(1) 列出第一个括号匹配部分,group(2) 列出第二个括号匹配部分,group(3) 列出第三个括号匹配部分。###
例子 

 findall()

re.findall遍历匹配,可以获取字符串中所有匹配的字符串,返回一个列表。

格式:

re.findall(pattern,string,flags=0)

1 import
2 p = re.compile(r'\d+')
3 print(p.findall('o1n2m3k4'))
4 执行结果如下:
5 ['1', '2', '3', '4']
例子
1 import re
2 tt = "Tina is a good girl, she is cool, clever, and so on..."
3 rr = re.compile(r'\w*oo\w*')
4 print(rr.findall(tt))
5 print(re.findall(r'(\w)*oo(\w)',tt))#()表示子表达式 
6 执行结果如下:
7 ['good', 'cool']
8 [('g', 'd'), ('c', 'l')]
例子

 finditer()

搜索string,返回一个顺序访问每一个结果(Match对象)的迭代器。找到re匹配的所有子串,并把它们作为一个迭代器返回。

格式:

re,finditer(pattern,string,flags=0)

 1 import re
 2 iter = re.finditer(r'\d+','12 drumm44ers drumming, 11 ... 10 ...')
 3 for i in iter:
 4     print(i)
 5     print(i.group())
 6     print(i.span())
 7 执行结果如下:
 8 <_sre.SRE_Match object; span=(0, 2), match='12'>
 9 12
10 (0, 2)
11 <_sre.SRE_Match object; span=(8, 10), match='44'>
12 44
13 (8, 10)
14 <_sre.SRE_Match object; span=(24, 26), match='11'>
15 11
16 (24, 26)
17 <_sre.SRE_Match object; span=(31, 33), match='10'>
18 10
19 (31, 33)
例子

split()

按照能够匹配的子串将string分割返回列表。

可以使用re.split来分割字符串,如:re.split(r'\s+',text);将字符串按空格分割成一个单词列表。

格式:

re.split(pattern,string,[maxsplit])

maxsplit用于指定最大分割次数,不指定将全部分割。

1 print(re.split('\d+','one1two2three3four4five5'))
2 执行结果如下:
3 ['one', 'two', 'three', 'four', 'five', '']
例子

sub()

使用re替换string中每一个匹配的子串后返回替换的字符串。

格式:

re.sub(pattern,repl,string,count)

import re
text = "JGood is a handsome boy, he is cool, clever, and so on..."
print(re.sub(r'\s+', '-', text))
执行结果如下:
JGood-is-a-handsome-boy,-he-is-cool,-clever,-and-so-on...
其中第二个函数是替换后的字符串;本例中为'-'

第四个参数指替换个数。默认为0,表示每个匹配项都替换。
例子

re.sub还允许使用函数对匹配项的替换进行复杂的处理。

如:re.sub(r"\s",lambda m:'[' +m.group(0) + ']', text,0);将字符串中的空格' '替换为'[' ']'。

1 import re
2 text = "JGood is a handsome boy, he is cool, clever, and so on..."
3 print(re.sub(r'\s+', lambda m:'['+m.group(0)+']', text,0))
4 执行结果如下:
5 JGood[ ]is[ ]a[ ]handsome[ ]boy,[ ]he[ ]is[ ]cool,[ ]clever,[ ]and[ ]so[ ]on...
例子

subn()

返回替换次数

格式:

subn(pattern,repl,string,count=0,flags=0)

1 import re
2 print(re.subn('[1-2]','A','123456abcdef'))
3 print(re.sub("g.t","have",'I get A,  I got B ,I gut C'))
4 print(re.subn("g.t","have",'I get A,  I got B ,I gut C'))
5 执行结果如下:
6 ('AA3456abcdef', 2)
7 I have A,  I have B ,I have C
8 ('I have A,  I have B ,I have C', 3)
例子

*注:

A、re.match与re.search与re.findall区别:

  • re.match之匹配字符串开始,如果字符串开始不符合正则表达式,则匹配失败,返回函数值None;而re.search和re.findall匹配整个字符串,直到找到一个匹配。
     1 a=re.search('[\d]',"abc33").group()
     2 print(a)
     3 p=re.match('[\d]',"abc33")
     4 print(p)
     5 b=re.findall('[\d]',"abc33")
     6 print(b)
     7 执行结果:
     8 3
     9 None
    10 ['3', '3']
    例子

B、贪婪匹配与非贪婪匹配

  • *?,+?,??,{m,n}?    前面的*,+,?等都是贪婪匹配,也就是尽可能匹配,后面加?号使其变成惰性匹配
     1 import re
     2 a = re.findall(r"a(\d+?)",'a23b')
     3 print(a)
     4 b = re.findall(r"a(\d+)",'a23b')
     5 print(b)
     6 执行结果:
     7 ['2']
     8 ['23']
     9 
    10 
    11 
    12 a = re.match('<(.*)>','<H1>title<H1>').group()
    13 print(a)
    14 b = re.match('<(.*?)>','<H1>title<H1>').group()
    15 print(b)
    16 执行结果:
    17 <H1>title<H1>
    18 <H1>
    19 
    20 
    21 a = re.findall(r"a(\d+)b",'a3333b')
    22 print(a)
    23 b = re.findall(r"a(\d+?)b",'a3333b')
    24 print(b)
    25 执行结果如下:
    26 ['3333']
    27 ['3333']
    28 #######################
    29 这里需要注意的是如果前后均有限定条件的时候,就不存在什么贪婪模式了,非匹配模式失效。
    例子

C、用flags时遇到的小坑

  • print(re.split('a','1A1a2A3',re.I))#输出结果并未能区分大小写
    这是因为re.split(pattern,string,maxsplit,flags)默认是四个参数,当我们传入的三个参数的时候,系统会默认re.I是第三个参数,所以就没起作用。如果想让这里的re.I起作用,写成flags=re.I即可。

常用模块二: 


 hashlib模块

Python的hashlib提供了常见的摘要算法,如MD5,SHA1等等。

摘要算法: 又称哈希算法、散列算法。它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用16进制的字符串表示)。

摘要算法就是通过摘要函数f()对任意长度的数据data计算出固定长度的摘要digest,目的是为了发现原始数据是否被人篡改过。

摘要算法之所以能指出数据是否被篡改过,就是因为摘要函数是一个单向函数,计算f(data)很容易,但通过digest反推data却非常困难。而且,对原始数据做一个bit的修改,都会导致计算出的摘要完全不同。

我们以常见的摘要算法MD5为例,计算出一个字符串的MD5值:

import hashlib

md5 = hashlib.md5()
md5.update('how to use md5 in python hashlib?'.encode('utf-8'))
print(md5.hexdigest())

#输出
d26a53750bc40b38b65a520292f69306

 

 

 

 如果数据量很大,可以分块多次调用update(),最后计算结果是一样的:

import hashlib
md5 = hashlib.md5()
md5.update('how to use md5 in '.encode('utf-8'))
md5.update('python hashlib?'.encode('utf-8'))
print(md5.hexdigest())
#输出
d26a53750bc40b38b65a520292f69306

 

MD5是最常见的摘要算法,速度很快,生成结果固定的128bit字节,通常用一个32位的16进制字符传表示。另一种常见的摘要算法式SHA1,调用SHA1和调用MD5完全类似:

import hashlib
 
sha1 = hashlib.sha1()
sha1.update('how to use sha1 in '.encode('utf-8'))
sha1.update('python hashlib?'.encode('utf-8'))
print sha1.hexdigest()

#输出
2c76b57293ce30acef38d98f6046927161b46a44

SHA1的结果是160 bit字节,通常用一个40位的16进制字符串表示。比SHA1更安全的算法是SHA256和SHA512,不过越安全的算法越慢,而且摘要长度更长。


 

configparser

待写。。。


 

logging

1.函数的简单配置

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

 

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

灵活配置日志级别,日志格式,输出位置:

import logging  
logging.basicConfig(level=logging.DEBUG,  
                    format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',  
                    datefmt='%a, %d %b %Y %H:%M:%S',  
                    filename='/tmp/test.log',  
                    filemode='w')  
  
logging.debug('debug message')  
logging.info('info message')  
logging.warning('warning message')  
logging.error('error message')  
logging.critical('critical message')

 

 

 

 

配置参数:

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参数会被忽略。

format参数中可能用到的格式化串:
%(name)s Logger的名字
%(levelno)s 数字形式的日志级别
%(levelname)s 文本形式的日志级别
%(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
%(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用户输出的消息
View Code

 

logger对象配置:

import logging

logger = logging.getLogger()
# 创建一个handler,用于写入日志文件
fh = logging.FileHandler('test.log',encoding='utf-8') 

# 再创建一个handler,用于输出到控制台 
ch = logging.StreamHandler() 
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setLevel(logging.DEBUG)

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

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')
View Code

logging库提供了多个组件:Logger、Handler、Filter、Formatter。Logger对象提供应用程序可直接使用的接口,Handler发送日志到适当的目的地,Filter提供了过滤日志信息的方法,Formatter指定日志显示格式。另外,可以通过:logger.setLevel(logging.Debug)设置级别,当然,也可以通过

fh.setLevel(logging.Debug)单对文件流设置某个级别。

 

 

posted @ 2018-08-12 16:59  飞天猪猪侠  阅读(230)  评论(0)    收藏  举报