Python之模块

Python之模块

  时间模块:

  import time

  time模块有三种方式来表示时间:时间戳,元组,格式化的时间字符串。

 (1)时间戳(给计算机看的):timestamp通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量,运行type(time.time()),返回的是float类型。

 (2)格式化的时间字符串(给人看的):Format String "1988-03-16"

 (3)元组(结构化时间:可以操作时间的):struct_time 元组共有9个元素(年、月、日、时、分、秒、一年中第几周、一年中第几天)

 1 # <1> 时间戳
 2 
 3 >>> import time
 4 >>> time.time()      #--------------返回当前时间的时间戳
 5 
 6 1493136727.099066
 7 
 8 # <2> 时间字符串
 9 
10 >>> time.strftime("%Y-%m-%d %X")
11 '2017-04-26 00:32:18'
12 
13 # <3> 时间元组
14 
15 >>> time.localtime()
16 time.struct_time(tm_year=2017, tm_mon=4, tm_mday=26,
17                  tm_hour=0, tm_min=32, tm_sec=42, tm_wday=2,
18                  tm_yday=116, tm_isdst=0)
View Code

   小结:时间戳是计算机能够识别的时间;时间字符串是人能够看懂的时间;元组则是用来操作时间的

 1 #一 时间戳<---->结构化时间:  localtime/gmtime   mktime
 2 import time
 3 time.localtime(3600*24)
 4 time.gmtime(3600*24)
 5 
 6 time.mktime(time.localtime())
 7 
 8 
 9 ##字符串时间<---->结构化时间: strftime/strptime
10 
11 time.strftime("%Y-%m-%d %X", time.localtime())
12 time.strptime("2017-03-16","%Y-%m-%d")
View Code

 

>>> time.asctime(time.localtime(312343423))
'Sun Nov 25 10:03:43 1979'
>>> time.ctime(312343423)
'Sun Nov 25 10:03:43 1979'


1 #--------------------------其他方法
2 # sleep(secs)
3 # 线程推迟指定的时间运行,单位为秒。

 

  random模块:

   random随机模块   

 1 import random
 2 random.random()      # 大于0且小于1之间的小数
 3 0.7664338663654585
 4 
 5 random.randint(1,5)  # 大于等于1且小于等于5之间的整数
 6 
 7 random.randrange(1,3) # 大于等于1且小于3之间的整数
 8 
 9 random.choice([1,'23',[4,5]])  # #1或者23或者[4,5]
10 
11 random.sample([1,'23',[4,5]],2) # #列表元素任意2个组合
12 [[4, 5], '23']
13 
14 random.uniform(1,3) #大于1小于3的小数
15 1.6270147180533838
16 
17 item=[1,3,5,7,9]
18 random.shuffle(item) # 打乱次序
19 item
20 [5, 1, 3, 7, 9]
21 random.shuffle(item)
22 item
23 [5, 9, 7, 1, 3]
View Code

   练习:生成验证码

 1 import random
 2 
 3 def v_code():
 4 
 5     code = ''
 6     for i in range(5):
 7 
 8         num=random.randint(0,9)
 9         alf=chr(random.randint(65,90))
10         add=random.choice([num,alf])
11         code="".join([code,str(add)])
12 
13     return code
14 
15 print(v_code())
View Code

 

 1 import random
 2 
 3 
 4 #print(random.random())
 5 
 6 #print(random.randint(1,4))  #[1,4]
 7 #print(random.randrange(1,3))  #[1,3)
 8 
 9 # print(random.choice([11,26,3,4]))
10 # print(random.sample([11,26,3,4],2))
11 
12 #print(random.uniform(1,3))
13 
14 # item=[1,23,33]
15 #
16 # random.shuffle(item)
17 # print(item)
18 
19 # a-z  A-Z
20 
21 
22 def validate():
23 
24     s=""
25     for i in range(5):
26          rNum=random.randint(0,9)
27          r_alph=chr(random.randint(65,90))
28 
29          ret=random.choice([str(rNum),r_alph])
30          s+=ret
31 
32     return s
33 
34 print(validate())
View Code

 

  hashiliib模块:

     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?')
print md5.hexdigest()

计算结果如下:
d26a53750bc40b38b65a520292f69306

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

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

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

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

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

 摘要算法应用:

  任何允许用户登录的网站都会存储用户登录的用户名和口令。如何存储用户名和口令呢?方法是存到数据库表中:

name    | password
--------+----------
michael | 123456
bob     | abc999
alice   | alice2008

如果以明文保存用户口令,如果数据库泄露,所有用户的口令就落入黑客的手里。此外,网站运维人员是可以访问数据库的,也就是能获取到所有用户的口令。正确的保存口令的方式是不存储用户的明文口令,而是存储用户口令的摘要,比如MD5:

username | password
---------+---------------------------------
michael  | e10adc3949ba59abbe56e057f20f883e
bob      | 878ef96e86145580c38c87f0410ad153
alice    | 99b1c2188db85afee403b1536010c2c9

考虑这么个情况,很多用户喜欢用123456,888888,password这些简单的口令,于是,黑客可以事先计算出这些常用口令的MD5值,得到一个反推表:

'e10adc3949ba59abbe56e057f20f883e': '123456'
'21218cca77804d2ba1922c33e0151105': '888888'
'5f4dcc3b5aa765d61d8327deb882cf99': 'password'

这样,无需破解,只需要对比数据库的MD5,黑客就获得了使用常用口令的用户账号。

对于用户来讲,当然不要使用过于简单的口令。但是,我们能否在程序设计上对简单口令加强保护呢?

由于常用口令的MD5值很容易被计算出来,所以,要确保存储的用户口令不是那些已经被计算出来的常用口令的MD5,这一方法通过对原始口令加一个复杂字符串来实现,俗称“加盐”:

hashlib.md5("salt".encode("utf8"))

经过Salt处理的MD5口令,只要Salt不被黑客知道,即使用户输入简单口令,也很难通过MD5反推明文口令。

但是如果有两个用户都使用了相同的简单口令比如123456,在数据库中,将存储两条相同的MD5值,这说明这两个用户的口令是一样的。有没有办法让使用相同口令的用户存储不同的MD5呢?

如果假定用户无法修改登录名,就可以通过把登录名作为Salt的一部分来计算MD5,从而实现相同口令的用户也存储不同的MD5。

摘要算法在很多地方都有广泛的应用。要注意摘要算法不是加密算法,不能用于加密(因为无法通过摘要反推明文),只能用于防篡改,但是它的单向计算特性决定了可以在不存储明文口令的情况下验证用户口令。

 

  练习:

import hashlib

m=hashlib.md5()

m.update("alex".encode("utf8"))  #534b44a19bf18d20b71ecc4eb77c572f

print(m.hexdigest())

m.update("alex".encode("utf8"))  #alexalex

print(m.hexdigest())

n=hashlib.md5("salt".encode("utf8")) #加盐
n.update(b"alexalex")
print(n.hexdigest())

# m=hashlib.sha1()

 

  os模块:

    os模块是与操作系统交互的一个接口。

'''
os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径
os.chdir("dirname")  改变当前脚本工作目录;相当于shell下cd
os.curdir  返回当前目录: ('.')
os.pardir  获取当前目录的父目录字符串名:('..')
os.makedirs('dirname1/dirname2')    可生成多层递归目录
os.removedirs('dirname1')    若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
os.mkdir('dirname')    生成单级目录;相当于shell中mkdir dirname
os.rmdir('dirname')    删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
os.listdir('dirname')    列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
os.remove()  删除一个文件
os.rename("oldname","newname")  重命名文件/目录
os.stat('path/filename')  获取文件/目录信息
os.sep    输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/"
os.linesep    输出当前平台使用的行终止符,win下为"\t\n",Linux下为"\n"
os.pathsep    输出用于分割文件路径的字符串 win下为;,Linux下为:
os.name    输出字符串指示当前使用平台。win->'nt'; Linux->'posix'
os.system("bash command")  运行shell命令,直接显示
os.environ  获取系统环境变量
os.path.abspath(path)  返回path规范化的绝对路径
os.path.split(path)  将path分割成目录和文件名二元组返回
os.path.dirname(path)  返回path的目录。其实就是os.path.split(path)的第一个元素
os.path.basename(path)  返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(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.getsize(path) 返回path的大小
'''

 

  注意:

   os.stat('path/filename')  获取文件/目录信息
stat 结构:

st_mode: inode 保护模式
st_ino: inode 节点号。
st_dev: inode 驻留的设备。
st_nlink: inode 的链接数。
st_uid: 所有者的用户ID。
st_gid: 所有者的组ID。
st_size: 普通文件以字节为单位的大小;包含等待某些特殊文件的数据。
st_atime: 上次访问的时间。
st_mtime: 最后一次修改的时间。
st_ctime: 由操作系统报告的"ctime"。在某些系统上(如Unix)是最新的元数据更改的时间,在其它系统上(如Windows)是创建时间(详细信息参见平台的文档)。

 

  练习:

import os

# print(os.getcwd())

# f=open("test.txt","w")

# os.chdir(r"C:\Users\Administrator\PycharmProjects\py_fullstack_s4\day32") # cd

# f=open("test2.txt","w")
# print(os.getcwd())

#os.makedirs("aaaaa/bbb")
#os.removedirs("aaaaa/bbb")

#print(os.listdir(r"C:\Users\Administrator\PycharmProjects\py_fullstack_s4\day33"))

# print(os.stat(r"C:\Users\Administrator\PycharmProjects\py_fullstack_s4\day33\test.txt"))


# '''
# os.stat_result(st_mode=33206, st_ino=10133099161702379, st_dev=3233102476, st_nlink=1, st_uid=0, st_gid=0, st_size=0, st_atime=1493176560, st_mtime=1493176614, st_ctime=1493176560)
#
# '''

# "yuan"+os.sep+"image"

#print(os.name)
#print(os.system("dir"))

# abs=os.path.abspath("test.txt")
# print(os.path.basename(abs))
# print(os.path.dirname(abs))

s1=r"C:\Users\Administrator\PycharmProjects"

s2=r"py_fullstack_s4\day33"

#print(s1+os.sep+s2)

ret=os.path.join(s1,s2)   # 推荐方式
print(ret)

 

  sys模块:

sys.argv           命令行参数List,第一个元素是程序本身路径
sys.exit(n)        退出程序,正常退出时exit(0)
sys.version        获取Python解释程序的版本信息
sys.maxint         最大的Int值
sys.path           返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform       返回操作系统平台名称
回到顶部

  

  logging日志模块:

     函数式简单配置 

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

  配置参数:

 1 logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用参数有:
 2 
 3 filename:用指定的文件名创建FiledHandler,这样日志会被存储在指定的文件中。
 4 filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。
 5 format:指定handler使用的日志显示格式。
 6 datefmt:指定日期时间格式。
 7 level:设置rootlogger(后边会讲解具体概念)的日志级别
 8 stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件(f=open(‘test.log’,’w’)),默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略。
 9 
10 format参数中可能用到的格式化串:
11 %(name)s Logger的名字
12 %(levelno)s 数字形式的日志级别
13 %(levelname)s 文本形式的日志级别
14 %(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
15 %(filename)s 调用日志输出函数的模块的文件名
16 %(module)s 调用日志输出函数的模块名
17 %(funcName)s 调用日志输出函数的函数名
18 %(lineno)d 调用日志输出函数的语句所在的代码行
19 %(created)f 当前时间,用UNIX标准的表示时间的浮 点数表示
20 %(relativeCreated)d 输出日志信息时的,自Logger创建以 来的毫秒数
21 %(asctime)s 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
22 %(thread)d 线程ID。可能没有
23 %(threadName)s 线程名。可能没有
24 %(process)d 进程ID。可能没有
25 %(message)s用户输出的消息
View Code

   logger对象配置:

import logging

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

# 再创建一个handler,用于输出到控制台
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和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')

 

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

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

 

 1 import logging
 2 
 3 import logging
 4 
 5 #  debug  info  warning(默认) error critical
 6 
 7 #1  congfig函数
 8 
 9 # logging.basicConfig(level=logging.DEBUG,
10 #                     format="%(asctime)s [%(lineno)s] %(message)s",
11 #                     datefmt="%Y-%m-%d %H:%M:%S",
12 #                     filename="logger",
13 #                     filemode="a"
14 #                     )
15 
16 # logging.debug('debug message')
17 # num=1000
18 # logging.info('cost %s'%num)
19 
20 # logging.warning('warning messagegfdsgsdfg') #
21 #
22 # logging.error('error message')
23 #
24 # logging.critical('critical message')
25 
26 
27 #配置两种方式: 1  congfig   2 logger
28 
29 # 2 logger对象
30 
31 def get_logger():
32 
33     logger=logging.getLogger()
34 
35     fh=logging.FileHandler("logger2")
36 
37     sh=logging.StreamHandler()
38 
39     logger.setLevel(logging.DEBUG)  #设定输出等级
40 
41     fm=logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
42 
43     logger.addHandler(fh)
44 
45     logger.addHandler(sh)
46 
47     fh.setFormatter(fm)
48     sh.setFormatter(fm)
49 
50     return logger
51 
52 Logger=get_logger()
53 
54 Logger.debug('logger debug message')
55 Logger.info('logger info message')
56 Logger.warning('logger warning message')
57 Logger.error('logger error message')
58 Logger.critical('logger critical message')
View Code

 

  *****json序列化模块*****:

    dumps  # 将字典d转为json字符串---序列化 ,那倒是的unicode的数据。

      loads    #将json字符串反序列化成之间的类型

 

    之前我们学习过用eval内置方法可以将一个字符串转成python对象,不过,eval方法是有局限性的,对于普通的数据类型,json.loads和eval都能用,但遇到特殊类型的时候,eval就不管用了,所以eval的重点还是通常用来执行一个字符串表达式,并返回表达式的值。 

 1 #---转换类型
 2 
 3 d={"name":"yuan"}
 4 
 5 s=str(d)
 6 
 7 print(type(s))
 8 
 9 d2=eval(s)
10 
11 print(d2[1])
12 
13 with open("test") as f:
14 
15     for i in f :
16 
17         if type(eval(i.strip()))==dict:
18             print(eval(i.strip())[1])
19             
20 # 计算
21 
22 print(eval("12*7+5-3"))
View Code

   什么是序列化?

  我们把对象(变量)从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling,在其他语言中也被称之为serialization,marshalling,flattening等等,都是一个意思。序列化之后,就可以把序列化后的内容写入磁盘,或者通过网络传输到别的机器上。反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickling。

    json模块: 

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

  JSON表示的对象就是标准的JavaScript语言的对象一个子集,JSON和Python内置的数据类型对应如下:

 

 1 import json
 2 i=10
 3 s='hello'
 4 t=(1,4,6)
 5 l=[3,5,7]
 6 d={'name':"yuan"}
 7 
 8 json_str1=json.dumps(i)
 9 json_str2=json.dumps(s)
10 json_str3=json.dumps(t)
11 json_str4=json.dumps(l)
12 json_str5=json.dumps(d)
13 
14 print(json_str1)   #'10'
15 print(json_str2)   #'"hello"'
16 print(json_str3)   #'[1, 4, 6]'
17 print(json_str4)   #'[3, 5, 7]'
18 print(json_str5)   #'{"name": "yuan"}'
View Code

 

python在文本中的使用: 

 1 #----------------------------序列化
 2 import json
 3 
 4 dic={'name':'alvin','age':23,'sex':'male'}
 5 print(type(dic))#<class 'dict'>
 6 
 7 data=json.dumps(dic)
 8 print("type",type(data))#<class 'str'>
 9 print("data",data)
10 
11 
12 f=open('序列化对象','w')
13 f.write(data)  #-------------------等价于json.dump(dic,f)
14 f.close()
15 
16 
17 #-----------------------------反序列化<br>
18 import json
19 f=open('序列化对象')
20 new_data=json.loads(f.read())#  等价于data=json.load(f)
21 
22 print(type(new_data))
View Code

 

  pickle序列化模块:

    pickle是无法读的。无法读取内容。

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

 

   shelve序列化模块:

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

 1 import shelve
 2   
 3 f = shelve.open(r'shelve.txt')
 4   
 5 # f['stu1_info']={'name':'alex','age':'18'}
 6 # f['stu2_info']={'name':'alvin','age':'20'}
 7 # f['school_info']={'website':'oldboyedu.com','city':'beijing'}
 8 #
 9 #
10 # f.close()
11   
12 print(f.get('stu_info')['age'])
View Code

 

  练习:   

  1 # d={"河北":["廊坊","保定"],"湖南":["长沙","韶山"]}
  2 #
  3 # s=str(d)
  4 # with open("data","w") as f:
  5 #     f.write(s)
  6 
  7 # with open("data") as f2:
  8 #     s2=f2.read()
  9 #     d2=eval(s2)
 10 #
 11 # print(d2["河北"]) # '{"河北":["廊坊","保定"],"湖南":["长沙","韶山"]}'
 12 
 13 # print(eval("12+34*34"))
 14 
 15 import json
 16 
 17 
 18 import json
 19 
 20 
 21 # i=10
 22 # s='hello'
 23 # t=(1,4,6)
 24 # l=[3,5,7]
 25 # d={'name':"yuan"}
 26 #
 27 # json_str1=json.dumps(i)
 28 # json_str2=json.dumps(s)
 29 # json_str3=json.dumps(t)
 30 # json_str4=json.dumps(l)
 31 # json_str5=json.dumps(d)
 32 #
 33 # print(json_str1)   #'10'
 34 # print(json_str2)   #'"hello"'
 35 # print(json_str3)   #'[1, 4, 6]'
 36 # print(json_str4)   #'[3, 5, 7]'
 37 # print(json_str5)   #'{"name": "yuan"}'
 38 
 39 
 40 
 41 # # d={"河北":["廊坊","保定"],"湖南":["长沙","韶山"]}
 42 #
 43 # d={'name':"egon"}
 44 #
 45 # # s=json.dumps(d)  # 将字典d转为json字符串---序列化 ,那倒是的unicode的数据
 46 # #
 47 # # print(type(s))
 48 # # print(s)
 49 # #
 50 # #
 51 # # f=open("new",'w')
 52 # #
 53 # # f.write(s)
 54 # #
 55 # # f.close()
 56 #
 57 # # -------------- dump方式
 58 #
 59 # # f=open("new2",'w')
 60 # # json.dump(d,f)#---------1 转成json字符串 2 将json字符串写入f里
 61 # #
 62 # # f.close()
 63 #
 64 #
 65 # #-----------------反序列化
 66 #
 67 # # f=open("new")
 68 # #
 69 # # data=f.read()
 70 # #
 71 # # data2=json.loads(data)
 72 # #
 73 # # print(data2["name"])
 74 
 75 
 76 #------练习
 77 
 78 # f=open("new3")
 79 # data=f.read()
 80 #
 81 # ret=json.loads(data)
 82 # # ret=[123]
 83 # print(type(ret[0]))
 84 
 85 
 86 
 87 #----------------------------------pickle--------------------
 88 
 89 
 90 import pickle
 91 
 92 
 93 import datetime
 94 
 95 t=datetime.datetime.now()
 96 
 97 
 98 # d={"data":t}
 99 
100 # json.dump(d,open("new4","w"))
101 
102 #d={"name":"alvin"}
103 
104 # s=pickle.dumps(d)
105 # print(s)
106 # print(type(s))
107 #
108 # f=open('new5',"wb")
109 #
110 # f.write(s)
111 # f.close()
112 
113 
114 # f=open("new5","rb")
115 #
116 # data=pickle.loads(f.read())
117 #
118 # print(data)
View Code

  

  ******re模块******:     

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

字符匹配(普通字符,元字符):

1 普通字符:大多数字符和字母都会和自身匹配
              >>> re.findall('alvin','yuanaleSxalexwupeiqi')
                      ['alvin'] 

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

  元字符:

  . ^ $

1 import re
2 
3 ret1=re.findall('李.','李爽\nalex\n李四\negon\nalvin\n李二')
4 
5 ret2=re.findall('^李.','李爽\nalex\n李四\negon\nalvin\n李二')
6 
7 ret3=re.findall('李.$','李爽\nalex\n李四\negon\nalvin\n李二')
View Code

  * + ? { }

 1 import re
 2 
 3 ret1=re.findall('李.*','李杰\nalex\n李莲英\negon\nalvin\n李二棍子')
 4 ret2=re.findall('李.+','李杰\nalex\n李莲英\negon\nalvin\n李二棍子')
 5 
 6 ret3=re.findall('(李.{1,2})\n','李杰\nalex\n李莲英\negon\nalvin\n李二棍子') # 设定优先级的原因
 7 
 8 # 匹配一个数字包括整型和浮点型
 9 ret4=re.findall('\d+\.?\d*','12.45,34,0.05,109')
10 
11 print(ret4)
View Code

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

ret=re.findall('131\d+?','1312312312')
print(ret)  ['1312']

  转义符 \

  1、反斜杠后边跟元字符去除特殊功能,比如\.

  2、反斜杠后边跟普通字符实现特殊功能,比如\d

1 \d  匹配任何十进制数;      它相当于类 [0-9]。
2 \D  匹配任何非数字字符;    它相当于类 [^0-9]。
3 \s  匹配任何空白字符;      它相当于类 [ \t\n\r\f\v]。
4 \S  匹配任何非空白字符;    它相当于类 [^ \t\n\r\f\v]。
5 \w  匹配任何字母数字字符;   它相当于类 [a-zA-Z0-9_]。
6 \W  匹配任何非字母数字字符; 它相当于类 [^a-zA-Z0-9_]
7 \b  匹配一个特殊字符边界,比如空格 ,&,#等
View Code

  让我们看一下\b的应用:

ret=re.findall(r'I\b','I am LIST')
print(ret)#['I']

  接下来我们试着匹配下“abc\le”中的‘c\l’:

 1 import re
 2 
 3 ret=re.findall('c\l','abc\le')
 4 print(ret)#[]
 5 
 6 ret=re.findall('c\\l','abc\le')
 7 print(ret)#[]
 8 
 9 ret=re.findall('c\\\\l','abc\le')
10 print(ret)#[]
11 
12 ret=re.findall(r'c\\l','abc\le')
13 print(ret)#[]
14 
15 
16 # \b是特殊符号所以,'abc\be'前面需要加r
17 ret=re.findall(r'c\\b',r'abc\be')
18 print(ret)#[]
View Code

  分组 ()

m = re.findall(r'(ad)+', 'add')
print(m)
 
ret=re.search('(?P<id>\d{2})/(?P<name>\w{3})','23/com')
print(ret.group())#23/com
print(ret.group('id'))#23

  元字符之|

ret=re.search('(ab)|\d','rabhdg8sd')
print(ret.group())#ab

  字符集[]

 1 #--------------------------------------------字符集[]
 2 ret=re.findall('a[bc]d','acd')
 3 print(ret)#['acd']
 4  
 5 ret=re.findall('[a-z]','acd')
 6 print(ret)#['a', 'c', 'd']
 7  
 8 ret=re.findall('[.*+]','a.cd+')
 9 print(ret)#['.', '+']
10  
11 #在字符集里有功能的符号: - ^ \
12  
13 ret=re.findall('[1-9]','45dha3')
14 print(ret)#['4', '5', '3']
15  
16 ret=re.findall('[^ab]','45bdha3')
17 print(ret)#['4', '5', 'd', 'h', '3']
18  
19 ret=re.findall('[\d]','45bdha3')
20 print(ret)#['4', '5', '3']
View Code

    贪婪匹配

 贪婪匹配:在满足匹配时,匹配尽可能长的字符串,默认情况下,采用贪婪匹配
1 string pattern1 = @"a.*c";   // greedy match 
2 Regex regex = new Regex(pattern1);
3 regex.Match("abcabc"); // return "abcabc"
4 非贪婪匹配:在满足匹配时,匹配尽可能短的字符串,使用?来表示非贪婪匹配
5 
6 string pattern1 = @"a.*?c";   // non-greedy match 
7 Regex regex = new Regex(pattern1);
8 regex.Match("abcabc"); // return "abc"
View Code
 几个常用的非贪婪匹配Pattern
*? 重复任意次,但尽可能少重复
+? 重复1次或更多次,但尽可能少重复
?? 重复0次或1次,但尽可能少重复
{n,m}? 重复n到m次,但尽可能少重复
{n,}? 重复n次以上,但尽可能少重复
.*?的用法:
--------------------------------

. 是任意字符
* 是取 0 至 无限长度
? 是非贪婪模式。
何在一起就是 取尽量少的任意字符,一般不会这么单独写,他大多用在:
.*?x

就是取前面任意长度的字符,直到一个x出现

      re模块下的常用方法


 1 import re
 2 
 3 re.findall('a','alvin yuan')    #返回所有满足匹配条件的结果,放在列表里
 4 
 5 re.search('a','alvin yuan').group()  
 6 
 7                #函数会在字符串内查找模式匹配,只到找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以
 8                # 通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。
 9  
10 
11 
12 re.match('a','abc').group()     #同search,不过尽在字符串开始处进行匹配
13  
14 
15 ret=re.split('[ab]','abcd')     #先按'a'分割得到''和'bcd',在对''和'bcd'分别按'b'分割
16 
17 print(ret)#['', '', 'cd']
18  
19 
20 ret=re.sub('\d','abc','alvin5yuan6',1)
21 
22 ret=re.subn('\d','abc','alvin5yuan6')
23 
24 
25 obj=re.compile('\d{3}')
26 ret=obj.search('abc123eeee')
27 print(ret.group())#123
28 
29 
30 import re
31 ret=re.finditer('\d','ds3sy4784a')
32 print(ret)        #<callable_iterator object at 0x10195f940>
33  
34 print(next(ret).group())
35 print(next(ret).group())
View Code

注意:

1 findall的优先级查询:

1 import re
2  
3 ret=re.findall('www.(baidu|oldboy).com','www.oldboy.com')
4 print(ret)#['oldboy']     这是因为findall会优先把匹配结果组里内容返回,如果想要匹配结果,取消权限即可
5  
6 ret=re.findall('www.(?:baidu|oldboy).com','www.oldboy.com')
7 print(ret)#['www.oldboy.com']
View Code

2 split的优先级查询

ret=re.split("\d+","yuan2egon56alex")
print(ret)

ret=re.split("(\d+)","yuan2egon56alex")
print(ret)

练习

1、匹配标签

1 import re
2 
3 print(re.findall("<(?P<tag_name>\w+)>\w+</(?P=tag_name)>","<h1>hello</h1>"))
4 print(re.search("<(?P<tag_name>\w+)>\w+</(?P=tag_name)>","<h1>hello</h1>"))
5 print(re.search(r"<(\w+)>\w+</\1>","<h1>hello</h1>"))
View Code 

2、匹配整数 

1 #匹配出所有的整数
2 import re
3 
4 #ret=re.findall(r"\d+{0}]","1-2*(60+(-40.35/5)-(-4*3))")
5 ret=re.findall(r"-?\d+\.\d*|(-?\d+)","1-2*(60+(-40.35/5)-(-4*3))")
6 ret.remove("")
7 
8 print(ret)
View Code

3、数字匹配 

 1 1、 匹配一段文本中的每行的邮箱
 2 
 3 2、 匹配一段文本中的每行的时间字符串,比如:‘1990-07-12’;
 4 
 5    分别取出1年的12个月(^(0?[1-9]|1[0-2])$)、
 6    一个月的31天:^((0?[1-9])|((1|2)[0-9])|30|31)$
 7 
 8 3、 匹配一段文本中所有的身份证数字。
 9 
10 4、 匹配qq号。(腾讯QQ号从10000开始)  [1,9][0,9]{4,}
11 
12 5、 匹配一个浮点数。       ^(-?\d+)(\.\d+)?$   或者  -?\d+\.?\d*
13 
14 6、 匹配汉字。             ^[\u4e00-\u9fa5]{0,}$ 
15 
16 7、 匹配出所有整数
View Code

4、爬虫练习

 1 import requests
 2 
 3 import re
 4 import json
 5 
 6 def getPage(url):
 7 
 8     response=requests.get(url)
 9     return response.text
10 
11 def parsePage(s):
12     
13     com=re.compile('<div class="item">.*?<div class="pic">.*?<em .*?>(?P<id>\d+).*?<span class="title">(?P<title>.*?)</span>'
14                    '.*?<span class="rating_num" .*?>(?P<rating_num>.*?)</span>.*?<span>(?P<comment_num>.*?)评价</span>',re.S)
15 
16     ret=com.finditer(s)
17     for i in ret:
18         yield {
19             "id":i.group("id"),
20             "title":i.group("title"),
21             "rating_num":i.group("rating_num"),
22             "comment_num":i.group("comment_num"),
23         }
24 
25 def main(num):
26 
27     url='https://movie.douban.com/top250?start=%s&filter='%num
28     response_html=getPage(url)
29     ret=parsePage(response_html)
30     print(ret)
31     f=open("move_info7","a",encoding="utf8")
32 
33     for obj in ret:
34         print(obj)
35         data=json.dumps(obj,ensure_ascii=False)
36         f.write(data+"\n")
37 
38 if __name__ == '__main__':
39     count=0
40     for i in range(10):
41         main(count)
42         count+=25
View Code

5、test

  1 # 正则:对字符串的模糊匹配
  2 
  3 # key:元字符(有特殊功能的字符)
  4 
  5 import re
  6 
  7 #   re.findall(pattern, string,) # 找到所有的匹配元素,返回列表
  8 
  9 #元字符介绍
 10 
 11 # . :匹配除\n以外的任意符号
 12 
 13 #print(re.findall("a.+d","abcd"))  
 14 
 15 
 16 # ^:从字符串开始位置匹配
 17 
 18 # $:从字符串结尾匹配
 19 
 20 # print(re.findall("^yuan","yuandashj342jhg234"))
 21 # print(re.findall("yuan$","yuandashj342jhg234yuan"))
 22 
 23 # * + ?  {} :重复
 24 
 25 #print(re.findall("[0-9]{4}","af5324jh523hgj34gkhg53453"))
 26 
 27 
 28 #贪婪匹配
 29 print(re.findall("\d+","af5324jh523hgj34gkhg53453"))
 30 
 31 #非贪婪匹配
 32 
 33 # print(re.findall("\d+?","af5324jh523hgj34gkhg53453"))
 34 # print(re.findall("(abc\d)*?","af5324jh523hgj34gkhg53453"))
 35 
 36 # 字符集 []: 起一个或者的意思
 37 
 38 # print(re.findall("a[bc]d","hasdabdjhacd"))
 39 
 40 #注意: * ,+.等元字符都是普通符号, - ^ \
 41 
 42 # print(re.findall("[0-9]+","dashj342jhg234"))
 43 # print(re.findall("[a-z]+","dashj342jhg234"))
 44 #
 45 # print(re.findall("[^\d]+","d2a2fhj87fgj"))
 46 
 47 
 48 # ():分组
 49 
 50 # print(re.findall("(ad)+","addd"))
 51 # print(re.findall("(ad)+yuan","adddyuangfsdui"))
 52 
 53 # print(re.findall("(?:ad)+yuan","adadyuangfsdui"))
 54 # print(re.findall("(?:\d)+yuan","adad678423yuang4234fsdui"))
 55 
 56 #命名分组
 57 
 58 #ret8=re.search(r"(?P<A>\w+)\\aticles\\(?P<id>\d{4})",r"yuan\aticles\1234")
 59 #ret8=re.search(r"a\\nb",r"a\nb")
 60 #print(ret8)
 61 
 62 # print(ret8.group("id"))
 63 # print(ret8.group("A"))
 64 
 65 
 66 # # |  :或
 67 #
 68 # print(re.findall("www\.(?:oldboy|baidu)\.com","www.oldboy.com"))
 69 
 70 # \:转义
 71 
 72 # 1 后面加一个元字符使其变成普通符号 \.  \*
 73 # 2 将一些普通符号变成特殊符号 比如 \d \w
 74 
 75 # print(re.findall("\d+\.?\d*\*\d+\.?\d*","-2*6+7*45+1.456*3-8/4"))
 76 # print(re.findall("\w","$da@s4 234"))
 77 # print(re.findall("a\sb","a badf"))
 78 
 79 # print(re.findall("\\bI","hello I am LIA"))
 80 # print(re.findall(r"\dI","hello 654I am LIA"))
 81 
 82 # print(re.findall(r"c\\l","abc\l"))
 83 
 84 
 85 #  re的方法
 86 
 87 
 88 # re.findall()
 89 
 90 
 91 # s=re.finditer("\d+","ad324das32")
 92 # print(s)
 93 #
 94 # print(next(s).group())
 95 # print(next(s).group())
 96 
 97 
 98 # "(3+7*2+27+7+(4/2+1))+3"
 99 
100 # search;只匹配第一个结果
101 
102 # ret=re.search("\d+","djksf34asd3")
103 # print(ret.group())
104 #
105 # #match:只在字符串开始的位置匹配
106 # ret=re.match("\d+","423djksf34asd3")
107 # print(ret.group())
108 
109 #split 分割
110 # s2=re.split("\d+","fhd3245jskf54skf453sd",2)
111 # print(s2)
112 #
113 # ret3=re.split("l","hello yuan")
114 # print(ret3)
115 #
116 # #sub: 替换
117 #
118 # ret4=re.sub("\d+","A","hello 234jkhh23",1)
119 # print(ret4)
120 #
121 # ret4=re.subn("\d+","A","hello 234jkhh23")
122 # print(ret4)
123 
124 
125 #compile: 编译方法
126 # c=re.compile("\d+")
127 #
128 # ret5=c.findall("hello32world53") #== re.findall("\d+","hello32world53")
129 # print(ret5)
130 
131 
132 #计算:"1 - 2 * ( (60-30*2+-96) - (-4*3)/ (16-3*2) )"
133 
134 # s1="1+-2++5"
135 #
136 # def addsub(s):
137 #     pass
138 #
139 # def muldiv(s): #(60-30*2+-96)
140 #     pass
141 #     return (60-60+-96)
142 #
143 # def f(s):
144 #     s.replace("+-","-")
145 #
146 #
147 # while re.search("\([^()]+\)", s):
148 #     res = re.search("\([^()]+\)", s) #(60-30*2+-96)
149 #     res=muldiv(res)
150 #     ret=addsub(res)
151 # else:
152 #     res = muldiv(res)
153 #     ret = addsub(res)
154 
155 
156 s="2"
157 
158 print(res.group())
View Code

 

作业:计算器

 

扩展:

  1 logging模块
  2 import logging  
  3 logging.debug('debug message')  
  4 logging.info('info message')  
  5 logging.warning('warning message')  
  6 logging.error('error message')  
  7 logging.critical('critical message')
  8 
  9 运行结果:
 10 C:\Python36\python.exe C:/Users/Administrator/PycharmProjects/py_fullstack_s4/day34/test.py
 11 WARNING:root:warning message
 12 ERROR:root:error message
 13 CRITICAL:root:critical message
 14 可以看出有一个默认的等级:debug--info--warning(默认)--error--critical
 15 
 16 配置的两种方式:
 17 1、congfig函数
 18 import logging  
 19 logging.basicConfig(level=logging.DEBUG,  
 20                     format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',  
 21                     datefmt='%a, %d %b %Y %H:%M:%S',  
 22                     filename='/tmp/test.log',  
 23                     filemode='w')
 24 
 25 logging.debug('debug message')  
 26 logging.info('info message')  
 27 logging.warning('warning message')  
 28 logging.error('error message')  
 29 logging.critical('critical message')
 30 level表示日志等级,选择DEBUG的话会将所有的都打印出来,最重要的就是format的内容,具体的配置参数如下:
 31 
 32 可见在logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用参数有
 33 filename:用指定的文件名创建FiledHandler(后边会具体讲解handler的概念),这样日志会被存储在指定的文件中。
 34 filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。
 35 format:指定handler使用的日志显示格式。 
 36 datefmt:指定日期时间格式。 
 37 level:设置rootlogger(后边会讲解具体概念)的日志级别 
 38 stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件(f=open('test.log','w')),默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略。
 39 
 40 format参数中可能用到的格式化串:
 41 %(name)s Logger的名字
 42 %(levelno)s 数字形式的日志级别
 43 %(levelname)s 文本形式的日志级别
 44 %(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
 45 %(filename)s 调用日志输出函数的模块的文件名
 46 %(module)s 调用日志输出函数的模块名
 47 %(funcName)s 调用日志输出函数的函数名
 48 %(lineno)d 调用日志输出函数的语句所在的代码行
 49 %(created)f 当前时间,用UNIX标准的表示时间的浮 点数表示
 50 %(relativeCreated)d 输出日志信息时的,自Logger创建以 来的毫秒数
 51 %(asctime)s 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
 52 %(thread)d 线程ID。可能没有
 53 %(threadName)s 线程名。可能没有
 54 %(process)d 进程ID。可能没有
 55 %(message)s用户输出的消息
 56 2、logger对象
 57 上述几个例子中我们了解到了logging.debug()、logging.info()、logging.warning()、logging.error()、logging.critical()(分别用以记录不同级别的日志信息),logging.basicConfig()(用默认日志格式(Formatter)为日志系统建立一个默认的流处理器(StreamHandler),设置基础配置(如日志级别等)并加到root logger(根Logger)中)这几个logging模块级别的函数,另外还有一个模块级别的函数是logging.getLogger([name])(返回一个logger对象,如果没有指定名字将返回root logger) 先看一个最简单的过程:
 58 
 59 import logging
 60 
 61 logger = logging.getLogger()
 62 # 创建一个handler,用于写入日志文件
 63 fh = logging.FileHandler('test.log')
 64 
 65 # 再创建一个handler,用于输出到控制台
 66 ch = logging.StreamHandler()
 67 
 68 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
 69 
 70 fh.setFormatter(formatter)
 71 ch.setFormatter(formatter)
 72 
 73 logger.addHandler(fh) #logger对象可以添加多个fh和ch对象
 74 logger.addHandler(ch)
 75 
 76 logger.debug('logger debug message')
 77 logger.info('logger info message')
 78 logger.warning('logger warning message')
 79 logger.error('logger error message')
 80 logger.critical('logger critical message')
 81 
 82 运行结果:
 83 2017-04-27 09:19:56,145 - root - WARNING - logger warning message
 84 2017-04-27 09:19:56,146 - root - ERROR - logger error message
 85 2017-04-27 09:19:56,146 - root - CRITICAL - logger critical message
 86 先简单介绍一下,logging库提供了多个组件:Logger、Handler、Filter、Formatter。Logger对象提供应用程序可直接使用的接口,Handler发送日志到适当的目的地,Filter提供了过滤日志信息的方法,Formatter指定日志显示格式。
 87 
 88 Logger是一个树形层级结构,输出信息之前都要获得一个Logger(如果没有显示的获取则自动创建并使用root Logger,如第一个例子所示)。
 89 
 90 logger = logging.getLogger()返回一个默认的Logger也即root Logger,并应用默认的日志级别、Handler和Formatter设置。 当然也可以通过Logger.setLevel(lel)指定最低的日志级别,可用的日志级别有logging.DEBUG、logging.INFO、logging.WARNING、logging.ERROR、logging.CRITICAL。
 91 
 92 Logger.debug()、Logger.info()、Logger.warning()、Logger.error()、Logger.critical()输出不同级别的日志,只有日志等级大于或等于设置的日志级别的日志才会被输出。
 93 
 94 logger.debug('logger debug message')  
 95 logger.info('logger info message')  
 96 logger.warning('logger warning message')  
 97 logger.error('logger error message')  
 98 logger.critical('logger critical message') 
 99 只输出了
100 
101 2014-05-06 12:54:43,222 - root - WARNING - logger warning message
102 2014-05-06 12:54:43,223 - root - ERROR - logger error message
103 2014-05-06 12:54:43,224 - root - CRITICAL - logger critical message
104 从这个输出可以看出logger = logging.getLogger()返回的Logger名为root。这里没有用logger.setLevel(logging.Debug)显示的为logger设置日志级别,所以使用默认的日志级别WARNIING,故结果只输出了大于等于WARNIING级别的信息。
105 
106 序列化模块(json、pickle)
107 什么是序列化?
108 我们把对象(变量)从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling,在其他语言中也被称之为serialization,marshalling,flattening等等,都是一个意思。
109 
110 序列化之后,就可以把序列化后的内容写入磁盘,或者通过网络传输到别的机器上。
111 
112 反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickling。
113 
114 json模块
115 如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML,但更好的方法是序列化为JSON,因为JSON表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。JSON不仅是标准格式,并且比XML更快,而且可以直接在Web页面中读取,非常方便。
116 
117 JSON表示的对象就是标准的JavaScript语言的对象,JSON和Python内置的数据类型对应如下:
118 
119 
120 
121 #----------------------------序列化
122 
123 import json
124 
125 dic={'name':'alvin','age':23,'sex':'male'}
126 print(type(dic))#<class 'dict'>
127 j=json.dumps(dic)
128 print(type(j))#<class 'str'>
129 f=open('序列化对象','w')
130 f.write(j)  #-------------------等价于json.dump(dic,f)
131 f.close()
132 #-----------------------------反序列化<br>
133 import json
134 f=open('序列化对象')
135 data=json.loads(f.read())#  等价于data=json.load(f)
136 d = {'name':'alvin','age':23,'sex':'male'}
137 
138 f = open("filename",'w')
139 
140 json.dump(d,f) #与dumps的区别在于将两步合成一步
141 
142 f.close()
143 
144 pickle模块
145 ##----------------------------序列化
146 import pickle
147 
148 dic={'name':'alvin','age':23,'sex':'male'}
149 print(type(dic))#<class 'dict'>
150 j=pickle.dumps(dic)
151 print(type(j))#<class 'bytes'>
152 f=open('序列化对象_pickle','wb')#注意是w是写入str,wb是写入bytes,j是'bytes'
153 f.write(j)  #-------------------等价于pickle.dump(dic,f
154 f.close()
155 #-------------------------反序列化
156 import pickle
157 f=open('序列化对象_pickle','rb')
158 data=pickle.loads(f.read())#  等价于data=pickle.load(f)
159 print(data['age'])  
160 Pickle的问题和所有其他编程语言特有的序列化问题一样,就是它只能用于Python,并且可能不同版本的Python彼此都不兼容,因此,只能用Pickle保存那些不重要的数据,不能成功地反序列化也没关系。
161 
162 re模块
163 就其本质而言,正则表达式(或 RE)是一种小型的、高度专业化的编程语言,(在Python中)它内嵌在Python中,并通过 re 模块实现。正则表达式模式被编译成一系列的字节码,然后由用 C 编写的匹配引擎执行。
164 
165 字符匹配(普通字符,元字符):
166 
167 1 普通字符:大多数字符和字母都会和自身匹配 >>> re.findall('alvin','yuanaleSxalexwupeiqi') ['alvin']
168 
169 2 元字符:. ^ $ * + ? { } [ ] | ( ) \
170 
171 re.findall("(?:ad)+yuan","adadyuangfsdui") #在(ad)分组中加入: '?:'表示去掉匹配默认的优先级,将字符串完全匹配出来,否则只匹配分组即括号中的内容
172 
173 管道符:| 表示匹配它两边的内容
174 
175 
176 
177 元字符之转义符\
178 
179 反斜杠后边跟元字符去除特殊功能,比如\.
180 反斜杠后边跟普通字符实现特殊功能,比如\d
181 
182 \d  匹配任何十进制数;它相当于类 [0-9]。
183 \D 匹配任何非数字字符;它相当于类 [^0-9]。
184 \s  匹配任何空白字符;它相当于类 [ \t\n\r\f\v]。
185 \S 匹配任何非空白字符;它相当于类 [^ \t\n\r\f\v]。
186 \w 匹配任何字母数字字符;它相当于类 [a-zA-Z0-9_]。
187 \W 匹配任何非字母数字字符;它相当于类 [^a-zA-Z0-9_]
188 \b  匹配一个特殊字符边界,比如空格 ,&,#等
189 使用\b的时候需要注意,因为它在ASCII码表中有特殊的意义,表示退格,在python中使用正则表达式,会将代码先交给Python解释器进行解释,而解释器也支持‘\’转义符号,然后再交给正则表达式进行匹配,故使用时应该用如下形式:
190 
191 ret=re.findall('c\\\\l','abc\le')
192 print(ret)
193 执行结果为:['c\\l']
194 
195 
196 re模块下的常用方法
197 import re
198 #1
199 re.findall('a','alvin yuan')    #返回所有满足匹配条件的结果,放在列表里
200 #2
201 re.search('a','alvin yuan').group()  #函数会在字符串内查找模式匹配,只到找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以
202  # 通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。
203 #3
204 re.match('a','abc').group()     #同search,不过尽在字符串开始处进行匹配
205 #4
206 ret=re.split('[ab]','abcd')     #先按'a'分割得到''和'bcd',在对''和'bcd'分别按'b'分割,可跟分割次数参数
207 print(ret)#['', '', 'cd']
208 #5
209 ret=re.sub('\d','abc','alvin5yuan6',1)
210 print(ret)#alvinabcyuan6
211 ret=re.subn('\d','abc','alvin5yuan6')
212 print(ret)#('alvinabcyuanabc', 2)
213 #6
214 obj=re.compile('\d{3}')
215 ret=obj.search('abc123eeee')
216 print(ret.group())#123
217 
218 
219 
220 import re
221 ret=re.finditer('\d','ds3sy4784a')
222 print(ret)  #<callable_iterator object at 0x10195f940>
223 print(next(ret).group())
224 print(next(ret).group())
225 
226 
227 import re
228 ret=re.findall('www.(baidu|oldboy).com','www.oldboy.com')
229 print(ret)#['oldboy']  这是因为findall会优先把匹配结果组里内容返回,如果想要匹配结果,取消权限即可
230 ret=re.findall('www.(?:baidu|oldboy).com','www.oldboy.com')
231 print(ret)#['www.oldboy.com']
232 命名分组
View Code
  1 ***
  2 #logging模块
  3     import logging  
  4     logging.debug('debug message')  
  5     logging.info('info message')  
  6     logging.warning('warning message')  
  7     logging.error('error message')  
  8     logging.critical('critical message')
  9     
 10     运行结果:
 11     C:\Python36\python.exe C:/Users/Administrator/PycharmProjects/py_fullstack_s4/day34/test.py
 12     WARNING:root:warning message
 13     ERROR:root:error message
 14     CRITICAL:root:critical message
 15 
 16 ***可以看出有一个默认的等级:debug--info--warning(默认)--error--critical***
 17 
 18 ##**配置的两种方式:**
 19 ###1、congfig函数   
 20 
 21     import logging  
 22     logging.basicConfig(level=logging.DEBUG,  
 23                         format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',  
 24                         datefmt='%a, %d %b %Y %H:%M:%S',  
 25                         filename='/tmp/test.log',  
 26                         filemode='w')
 27       
 28     logging.debug('debug message')  
 29     logging.info('info message')  
 30     logging.warning('warning message')  
 31     logging.error('error message')  
 32     logging.critical('critical message')
 33 
 34 ***level表示日志等级,选择DEBUG的话会将所有的都打印出来,最重要的就是format的内容,具体的配置参数如下:***
 35 
 36     可见在logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用参数有
 37     filename:用指定的文件名创建FiledHandler(后边会具体讲解handler的概念),这样日志会被存储在指定的文件中。
 38     filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。
 39     format:指定handler使用的日志显示格式。 
 40     datefmt:指定日期时间格式。 
 41     level:设置rootlogger(后边会讲解具体概念)的日志级别 
 42     stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件(f=open('test.log','w')),默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略。
 43     
 44     format参数中可能用到的格式化串:
 45     %(name)s Logger的名字
 46     %(levelno)s 数字形式的日志级别
 47     %(levelname)s 文本形式的日志级别
 48     %(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
 49     %(filename)s 调用日志输出函数的模块的文件名
 50     %(module)s 调用日志输出函数的模块名
 51     %(funcName)s 调用日志输出函数的函数名
 52     %(lineno)d 调用日志输出函数的语句所在的代码行
 53     %(created)f 当前时间,用UNIX标准的表示时间的浮 点数表示
 54     %(relativeCreated)d 输出日志信息时的,自Logger创建以 来的毫秒数
 55     %(asctime)s 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
 56     %(thread)d 线程ID。可能没有
 57     %(threadName)s 线程名。可能没有
 58     %(process)d 进程ID。可能没有
 59     %(message)s用户输出的消息
 60 
 61 
 62 ###2、logger对象
 63 >上述几个例子中我们了解到了logging.debug()、logging.info()、logging.warning()、logging.error()、logging.critical()(分别用以记录不同级别的日志信息),logging.basicConfig()(用默认日志格式(Formatter)为日志系统建立一个默认的流处理器(StreamHandler),设置基础配置(如日志级别等)并加到root logger(根Logger)中)这几个logging模块级别的函数,另外还有一个模块级别的函数是logging.getLogger([name])(返回一个logger对象,如果没有指定名字将返回root logger)
 64 先看一个最简单的过程:
 65 
 66     import logging
 67     
 68     logger = logging.getLogger()
 69     # 创建一个handler,用于写入日志文件
 70     fh = logging.FileHandler('test.log')
 71     
 72     # 再创建一个handler,用于输出到控制台
 73     ch = logging.StreamHandler()
 74     
 75     formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
 76     
 77     fh.setFormatter(formatter)
 78     ch.setFormatter(formatter)
 79     
 80     logger.addHandler(fh) #logger对象可以添加多个fh和ch对象
 81     logger.addHandler(ch)
 82     
 83     logger.debug('logger debug message')
 84     logger.info('logger info message')
 85     logger.warning('logger warning message')
 86     logger.error('logger error message')
 87     logger.critical('logger critical message')
 88     
 89     运行结果:
 90     2017-04-27 09:19:56,145 - root - WARNING - logger warning message
 91     2017-04-27 09:19:56,146 - root - ERROR - logger error message
 92     2017-04-27 09:19:56,146 - root - CRITICAL - logger critical message
 93 
 94 >先简单介绍一下,logging库提供了多个组件:Logger、Handler、Filter、Formatter。Logger对象提供应用程序可直接使用的接口,Handler发送日志到适当的目的地,Filter提供了过滤日志信息的方法,Formatter指定日志显示格式。
 95 >
 96   Logger是一个树形层级结构,输出信息之前都要获得一个Logger(如果没有显示的获取则自动创建并使用root Logger,如第一个例子所示)。
 97 
 98 > logger = logging.getLogger()返回一个默认的Logger也即root Logger,并应用默认的日志级别、Handler和Formatter设置。
 99 当然也可以通过Logger.setLevel(lel)指定最低的日志级别,可用的日志级别有logging.DEBUG、logging.INFO、logging.WARNING、logging.ERROR、logging.CRITICAL。
100 
101 >Logger.debug()、Logger.info()、Logger.warning()、Logger.error()、Logger.critical()输出不同级别的日志,只有日志等级大于或等于设置的日志级别的日志才会被输出。
102 
103     logger.debug('logger debug message')  
104     logger.info('logger info message')  
105     logger.warning('logger warning message')  
106     logger.error('logger error message')  
107     logger.critical('logger critical message') 
108 
109 >只输出了
110 
111     2014-05-06 12:54:43,222 - root - WARNING - logger warning message
112     2014-05-06 12:54:43,223 - root - ERROR - logger error message
113     2014-05-06 12:54:43,224 - root - CRITICAL - logger critical message
114 >从这个输出可以看出logger = logging.getLogger()返回的Logger名为root。这里没有用logger.setLevel(logging.Debug)显示的为logger设置日志级别,所以使用默认的日志级别WARNIING,故结果只输出了大于等于WARNIING级别的信息。
115 
116 ***
117 #序列化模块(json、pickle)
118 ###什么是序列化?
119 >我们把对象(变量)从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling,在其他语言中也被称之为serialization,marshalling,flattening等等,都是一个意思。
120 
121 >序列化之后,就可以把序列化后的内容写入磁盘,或者通过网络传输到别的机器上。
122 
123 >反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickling。
124 
125 ##json模块
126 >如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML,但更好的方法是序列化为JSON,因为JSON表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。JSON不仅是标准格式,并且比XML更快,而且可以直接在Web页面中读取,非常方便。
127 
128 >JSON表示的对象就是标准的JavaScript语言的对象,JSON和Python内置的数据类型对应如下:
129 
130 ![](http://i.imgur.com/qbLGmCl.png)
131 
132 
133     #----------------------------序列化
134     
135     import json
136     
137     dic={'name':'alvin','age':23,'sex':'male'}
138     print(type(dic))#<class 'dict'>
139     j=json.dumps(dic)
140     print(type(j))#<class 'str'>
141     f=open('序列化对象','w')
142     f.write(j)  #-------------------等价于json.dump(dic,f)
143     f.close()
144     #-----------------------------反序列化<br>
145     import json
146     f=open('序列化对象')
147     data=json.loads(f.read())#  等价于data=json.load(f)
148 
149 >d = {'name':'alvin','age':23,'sex':'male'}
150 >
151 >f = open("filename",'w')
152 >
153 >json.dump(d,f)   #与dumps的区别在于将两步合成一步
154 >
155 >f.close()
156 
157 
158 ##pickle模块
159     ##----------------------------序列化
160     import pickle
161     
162     dic={'name':'alvin','age':23,'sex':'male'}
163     print(type(dic))#<class 'dict'>
164     j=pickle.dumps(dic)
165     print(type(j))#<class 'bytes'>
166     f=open('序列化对象_pickle','wb')#注意是w是写入str,wb是写入bytes,j是'bytes'
167     f.write(j)  #-------------------等价于pickle.dump(dic,f
168     f.close()
169     #-------------------------反序列化
170     import pickle
171     f=open('序列化对象_pickle','rb')
172     data=pickle.loads(f.read())#  等价于data=pickle.load(f)
173     print(data['age'])  
174 >Pickle的问题和所有其他编程语言特有的序列化问题一样,就是它只能用于Python,并且可能不同版本的Python彼此都不兼容,因此,只能用Pickle保存那些不重要的数据,不能成功地反序列化也没关系。
175 
176 ***
177 #re模块
178 
179 >就其本质而言,正则表达式(或 RE)是一种小型的、高度专业化的编程语言,(在Python中)它内嵌在Python中,并通过 re 模块实现。正则表达式模式被编译成一系列的字节码,然后由用 C 编写的匹配引擎执行。
180 
181 >字符匹配(普通字符,元字符):
182 
183 >>1 普通字符:大多数字符和字母都会和自身匹配
184               >>> re.findall('alvin','yuanaleSxalexwupeiqi')
185                       ['alvin'] 
186 
187 >>2 元字符:. ^ $ * + ? { } [ ] | ( ) \
188 
189 
190 **re.findall("(?:ad)+yuan","adadyuangfsdui") #在(ad)分组中加入: '?:'表示去掉匹配默认的优先级,将字符串完全匹配出来,否则只匹配分组即括号中的内容**
191 
192 **管道符:| 表示匹配它两边的内容**
193 
194 ![](http://i.imgur.com/lnTzTy9.png)
195 
196     元字符之转义符\
197     
198     反斜杠后边跟元字符去除特殊功能,比如\.
199     反斜杠后边跟普通字符实现特殊功能,比如\d
200     
201     \d  匹配任何十进制数;它相当于类 [0-9]。
202     \D 匹配任何非数字字符;它相当于类 [^0-9]。
203     \s  匹配任何空白字符;它相当于类 [ \t\n\r\f\v]。
204     \S 匹配任何非空白字符;它相当于类 [^ \t\n\r\f\v]。
205     \w 匹配任何字母数字字符;它相当于类 [a-zA-Z0-9_]。
206     \W 匹配任何非字母数字字符;它相当于类 [^a-zA-Z0-9_]
207     \b  匹配一个特殊字符边界,比如空格 ,&,#等
208 
209 **使用\b的时候需要注意,因为它在ASCII码表中有特殊的意义,表示退格,在python中使用正则表达式,会将代码先交给Python解释器进行解释,而解释器也支持‘\’转义符号,然后再交给正则表达式进行匹配,故使用时应该用如下形式:**
210 
211     ret=re.findall('c\\\\l','abc\le')
212     print(ret)
213     执行结果为:['c\\l']
214 
215 ![](http://i.imgur.com/Rvkvgi3.png)
216 
217 ###re模块下的常用方法
218 
219     
220     import re
221     #1
222     re.findall('a','alvin yuan')    #返回所有满足匹配条件的结果,放在列表里
223     #2
224     re.search('a','alvin yuan').group()  #函数会在字符串内查找模式匹配,只到找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以
225      # 通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。
226     #3
227     re.match('a','abc').group()     #同search,不过尽在字符串开始处进行匹配
228     #4
229     ret=re.split('[ab]','abcd')     #先按'a'分割得到''和'bcd',在对''和'bcd'分别按'b'分割,可跟分割次数参数
230     print(ret)#['', '', 'cd']
231     #5
232     ret=re.sub('\d','abc','alvin5yuan6',1)
233     print(ret)#alvinabcyuan6
234     ret=re.subn('\d','abc','alvin5yuan6')
235     print(ret)#('alvinabcyuanabc', 2)
236     #6
237     obj=re.compile('\d{3}')
238     ret=obj.search('abc123eeee')
239     print(ret.group())#123
240 
241     
242     
243     import re
244     ret=re.finditer('\d','ds3sy4784a')
245     print(ret)  #<callable_iterator object at 0x10195f940>
246     print(next(ret).group())
247     print(next(ret).group())
248 
249         
250     import re
251     ret=re.findall('www.(baidu|oldboy).com','www.oldboy.com')
252     print(ret)#['oldboy']  这是因为findall会优先把匹配结果组里内容返回,如果想要匹配结果,取消权限即可
253     ret=re.findall('www.(?:baidu|oldboy).com','www.oldboy.com')
254     print(ret)#['www.oldboy.com']
255 
256 ###命名分组
257 
258 ![](http://i.imgur.com/Q6d7y97.png)
View Code 

 

 

模块链接:常用模块

posted @ 2018-07-03 19:58  王先生是胖子  阅读(235)  评论(0编辑  收藏  举报