模块
一.时间time模块:
时间模块有3种形式:
1.时间戳:time.time( ) 按秒计算,从1970年开始到现在走过的秒数
2.时间字符串:time.strftime( ) 按某种自己定义的格式输出时间
3.结构化时间:time.structime( )
结构化的时间(struct_time):struct_time元组共有9个元素共九个元素:(年,月,日,时,分,秒,一年中第几周,一年中第几天,夏令时)
对应的是:(tm_year=2017, tm_mon=12, tm_mday=14, tm_hour=23,
tm_min=54, tm_sec=13, tm_wday=3, tm_yday=348, tm_isdst=0)
import time print(time.time()) print(time.strftime('%Y-%m-%d %X')) print(time.localtime()) print(time.gmtime()) # 时间戳,字符串格式时间,结构化的时间的之间的转换 print(time.localtime(12121212212)) print(time.mktime(time.localtime(12122121212))) print(time.strftime('%Y-%m-%d %X',time.localtime())) print(time.strptime('2012-12-12 12:12:05','%Y-%m-%d %X')) print(time.ctime()) print(time.asctime(time.localtime())) >>>>>>>>>> 1513266853.1306016 2017-12-14 23:54:13 time.struct_time(tm_year=2017, tm_mon=12, tm_mday=14, tm_hour=23, tm_min=54, tm_sec=13, tm_wday=3, tm_yday=348, tm_isdst=0) time.struct_time(tm_year=2017, tm_mon=12, tm_mday=14, tm_hour=15, tm_min=54, tm_sec=13, tm_wday=3, tm_yday=348, tm_isdst=0) time.struct_time(tm_year=2354, tm_mon=2, tm_mday=9, tm_hour=3, tm_min=23, tm_sec=32, tm_wday=1, tm_yday=40, tm_isdst=0) 12122121212.0 2017-12-14 23:54:13 time.struct_time(tm_year=2012, tm_mon=12, tm_mday=12, tm_hour=12, tm_min=12, tm_sec=5, tm_wday=2, tm_yday=347, tm_isdst=-1) Thu Dec 14 23:54:13 2017 Thu Dec 14 23:54:13 2017
二.随机数模块 random
import random print(random.random())#(0,1)----float 大于0且小于1之间的小数 print(random.randint(1,3)) #[1,3] 大于等于1且小于等于3之间的整数 print(random.randrange(1,3)) #[1,3) 大于等于1且小于3之间的整数 print(random.choice([1,'23',[4,5]]))#1或者23或者[4,5] print(random.sample([1,'23',[4,5]],2))#列表元素任意2个组合 print(random.uniform(1,3))#大于1小于3的小数,如1.927109612082716 item=[1,3,5,7,9] random.shuffle(item) #打乱item的顺序,相当于"洗牌" print(item)
随机验证码:
1 import random
2 def check_code(): 3 s = '' 4 for i in range(5): 5 rNum = random.randint(0,9) 6 R_alpha = chr(random.randint(65,90)) 7 r_alpha = chr(random.randint(97,122)) 8 res = random.choice([str(rNum),r_alpha,R_alpha]) 9 s += res 10 return s 11 print(check_code())
三.摘要算法 hashlib 模块
摘要算法的特点:hash:一种算法 ,3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法
三个特点:
1.内容相同则hash运算结果相同,内容稍微改变则hash值则变
2.不可逆推
3.相同算法:无论校验多长的数据,得到的哈希值长度固定。
1.md5算法: import hashlib m = hashlib.md5() m.update('wuzetian'.encode('utf-8')) print(m.hexdigest()) >>>>>>>>> 33b751484e6abe814c1b5834118a44d3 2.hmac算法: import hmac h = hmac.new(b'yuan') #对数据类型定义相同的key,无论进行多少次迭代摘要,得到的数据字符串都是 h.update(b'hello') 相同的 h.update(b'world') print(h.hexdigest()) h1 = hmac.new(b'yuan') #key与h相同 h1.update(b'helloworld') print(h1.hexdigest()) h2 = hmac.new(b'yuanhelloworld') #key与h h1都不同 print(h2.hexdigest()) >>>>>>>>>>>>> cb4c5d67ddba310cdb31731905f73c52 cb4c5d67ddba310cdb31731905f73c52 7fe9e01174e0022f06b578d6822dd7e9
四.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的大小
在Linux和Mac平台上,该函数会原样返回path,在windows平台上会将路径中所有字符转换为小写,并将所有斜杠转换为饭斜杠。 >>> os.path.normcase('c:/windows\\system32\\') 'c:\\windows\\system32\\' 规范化路径,如..和/ >>> os.path.normpath('c://windows\\System32\\../Temp/') 'c:\\windows\\Temp' >>> a='/Users/jieli/test1/\\\a1/\\\\aa.py/../..' >>> print(os.path.normpath(a)) /Users/jieli/test1 >>>>>>>>>>>>>>>>>>>>>>>> os路径处理 #方式一:推荐使用 import os #具体应用 import os,sys possible_topdir = os.path.normpath(os.path.join( os.path.abspath(__file__), os.pardir, #上一级 os.pardir, os.pardir )) sys.path.insert(0,possible_topdir) #方式二:不推荐使用 os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
五.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 返回操作系统平台名称
1 #=========知识储备========== 2 #进度条的效果 3 [# ] 4 [## ] 5 [### ] 6 [#### ] 7 8 #指定宽度 9 print('[%-15s]' %'#') 10 print('[%-15s]' %'##') 11 print('[%-15s]' %'###') 12 print('[%-15s]' %'####') 13 14 #打印% 15 print('%s%%' %(100)) #第二个%号代表取消第一个%的特殊意义 16 17 #可传参来控制宽度 18 print('[%%-%ds]' %50) #[%-50s] 19 print(('[%%-%ds]' %50) %'#') 20 print(('[%%-%ds]' %50) %'##') 21 print(('[%%-%ds]' %50) %'###') 22 23 24 #=========实现打印进度条函数========== 25 import sys 26 import time 27 28 def progress(percent,width=50): 29 if percent >= 1: 30 percent=1 31 show_str=('[%%-%ds]' %width) %(int(width*percent)*'#') 32 print('\r%s %d%%' %(show_str,int(100*percent)),file=sys.stdout,flush=True,end='') 33 34 35 #=========应用========== 36 data_size=1025 37 recv_size=0 38 while recv_size < data_size: 39 time.sleep(0.1) #模拟数据的传输延迟 40 recv_size+=1024 #每次收1024 41 42 percent=recv_size/data_size #接收的比例 43 progress(percent,width=70) #进度条的宽度70 44 45 打印进度条
六.logging模块 日志模块
1.默认级别为warning,打印到终端
import logging logging.debug('调试debug') logging.info('消息info') logging.warning('警告warn') logging.error('错误error') logging.critical('严重critical') ''' WARNING:root:警告warn ERROR:root:错误error CRITICAL:root:严重critical '''
2.为logging模块指定全局配置,针对所有logger有效,控制打印到文件中
可在logging.basicConfig()函数中通过具体参数来更改logging模块默认行为,可用参数有 filename:用指定的文件名创建FiledHandler(后边会具体讲解handler的概念),这样日志会被存储在指定的文件中。 filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。 format:指定handler使用的日志显示格式。 datefmt:指定日期时间格式。 level:设置rootlogger(后边会讲解具体概念)的日志级别 stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件,默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略。 #格式 %(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:用户输出的消息 logging.basicConfig()
1 #======介绍 2 可在logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用参数有 3 filename:用指定的文件名创建FiledHandler(后边会具体讲解handler的概念),这样日志会被存储在指定的文件中。 4 filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。 5 format:指定handler使用的日志显示格式。 6 datefmt:指定日期时间格式。 7 level:设置rootlogger(后边会讲解具体概念)的日志级别 8 stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件,默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略。 9 10 11 format参数中可能用到的格式化串: 12 %(name)s Logger的名字 13 %(levelno)s 数字形式的日志级别 14 %(levelname)s 文本形式的日志级别 15 %(pathname)s 调用日志输出函数的模块的完整路径名,可能没有 16 %(filename)s 调用日志输出函数的模块的文件名 17 %(module)s 调用日志输出函数的模块名 18 %(funcName)s 调用日志输出函数的函数名 19 %(lineno)d 调用日志输出函数的语句所在的代码行 20 %(created)f 当前时间,用UNIX标准的表示时间的浮 点数表示 21 %(relativeCreated)d 输出日志信息时的,自Logger创建以 来的毫秒数 22 %(asctime)s 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒 23 %(thread)d 线程ID。可能没有 24 %(threadName)s 线程名。可能没有 25 %(process)d 进程ID。可能没有 26 %(message)s用户输出的消息 27 28 29 30 31 #========使用 32 import logging 33 logging.basicConfig(filename='access.log', 34 format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s', 35 datefmt='%Y-%m-%d %H:%M:%S %p', 36 level=10) 37 38 logging.debug('调试debug') 39 logging.info('消息info') 40 logging.warning('警告warn') 41 logging.error('错误error') 42 logging.critical('严重critical') 43 44 45 46 47 48 #========结果 49 access.log内容: 50 2017-07-28 20:32:17 PM - root - DEBUG -test: 调试debug 51 2017-07-28 20:32:17 PM - root - INFO -test: 消息info 52 2017-07-28 20:32:17 PM - root - WARNING -test: 警告warn 53 2017-07-28 20:32:17 PM - root - ERROR -test: 错误error 54 2017-07-28 20:32:17 PM - root - CRITICAL -test: 严重critical 55 56 part2: 可以为logging模块指定模块级的配置,即所有logger的配置
3.logging模块的Formatter,logger,Handler,Filter对象:
原理图:https://pan.baidu.com/s/1skWyTT7
#logger:产生日志的对象 #Filter:过滤日志的对象 #Handler:接收日志然后控制打印到不同的地方,FileHandler用来打印到文件中,StreamHandler用来打印到终端 #Formatter对象:可以定制不同的日志格式对象,然后绑定给不同的Handler对象使用,以此来控制不同的Handler的日志格式
1 ''' 2 critical=50 3 error =40 4 warning =30 5 info = 20 6 debug =10 7 ''' 8 9 10 import logging 11 12 #1、logger对象:负责产生日志,然后交给Filter过滤,然后交给不同的Handler输出 13 logger=logging.getLogger(__file__) 14 15 #2、Filter对象:不常用,略 16 17 #3、Handler对象:接收logger传来的日志,然后控制输出 18 h1=logging.FileHandler('t1.log') #打印到文件 19 h2=logging.FileHandler('t2.log') #打印到文件 20 h3=logging.StreamHandler() #打印到终端 21 22 #4、Formatter对象:日志格式 23 formmater1=logging.Formatter('%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s', 24 datefmt='%Y-%m-%d %H:%M:%S %p',) 25 26 formmater2=logging.Formatter('%(asctime)s : %(message)s', 27 datefmt='%Y-%m-%d %H:%M:%S %p',) 28 29 formmater3=logging.Formatter('%(name)s %(message)s',) 30 31 32 #5、为Handler对象绑定格式 33 h1.setFormatter(formmater1) 34 h2.setFormatter(formmater2) 35 h3.setFormatter(formmater3) 36 37 #6、将Handler添加给logger并设置日志级别 38 logger.addHandler(h1) 39 logger.addHandler(h2) 40 logger.addHandler(h3) 41 logger.setLevel(10) 42 43 #7、测试 44 logger.debug('debug') 45 logger.info('info') 46 logger.warning('warning') 47 logger.error('error') 48 logger.critical('critical')
4.Handler与logger的级别
logger是第一级过滤,然后才能到handler,我们可以给logger和handler同时设置level,但是需要注意的是
Logger is also the first to filter the message based on a level — if you set the logger to INFO, and all handlers to DEBUG, you still won't receive DEBUG messages on handlers — they'll be rejected by the logger itself. If you set logger to DEBUG, but all handlers to INFO, you won't receive any DEBUG messages either — because while the logger says "ok, process this", the handlers reject it (DEBUG < INFO). #验证 import logging form=logging.Formatter('%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S %p',) ch=logging.StreamHandler() ch.setFormatter(form) # ch.setLevel(10) ch.setLevel(20) l1=logging.getLogger('root') # l1.setLevel(20) l1.setLevel(10) l1.addHandler(ch) l1.debug('l1 debug') 重要,重要,重要!!!
5.应用
1 """ 2 logging配置 3 """ 4 5 import os 6 import logging.config 7 8 # 定义三种日志输出格式 开始 9 10 standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \ 11 '[%(levelname)s][%(message)s]' #其中name为getlogger指定的名字 12 13 simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s' 14 15 id_simple_format = '[%(levelname)s][%(asctime)s] %(message)s' 16 17 # 定义日志输出格式 结束 18 19 logfile_dir = os.path.dirname(os.path.abspath(__file__)) # log文件的目录 20 21 logfile_name = 'all2.log' # log文件名 22 23 # 如果不存在定义的日志目录就创建一个 24 if not os.path.isdir(logfile_dir): 25 os.mkdir(logfile_dir) 26 27 # log文件的全路径 28 logfile_path = os.path.join(logfile_dir, logfile_name) 29 30 # log配置字典 31 LOGGING_DIC = { 32 'version': 1, 33 'disable_existing_loggers': False, 34 'formatters': { 35 'standard': { 36 'format': standard_format 37 }, 38 'simple': { 39 'format': simple_format 40 }, 41 }, 42 'filters': {}, 43 'handlers': { 44 #打印到终端的日志 45 'console': { 46 'level': 'DEBUG', 47 'class': 'logging.StreamHandler', # 打印到屏幕 48 'formatter': 'simple' 49 }, 50 #打印到文件的日志,收集info及以上的日志 51 'default': { 52 'level': 'DEBUG', 53 'class': 'logging.handlers.RotatingFileHandler', # 保存到文件 54 'formatter': 'standard', 55 'filename': logfile_path, # 日志文件 56 'maxBytes': 1024*1024*5, # 日志大小 5M 57 'backupCount': 5, 58 'encoding': 'utf-8', # 日志文件的编码,再也不用担心中文log乱码了 59 }, 60 }, 61 'loggers': { 62 #logging.getLogger(__name__)拿到的logger配置 63 '': { 64 'handlers': ['default', 'console'], # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕 65 'level': 'DEBUG', 66 'propagate': True, # 向上(更高level的logger)传递 67 }, 68 }, 69 } 70 71 72 def load_my_logging_cfg(): 73 logging.config.dictConfig(LOGGING_DIC) # 导入上面定义的logging配置 74 logger = logging.getLogger(__name__) # 生成一个log实例 75 logger.info('It works!') # 记录该文件的运行状态 76 77 if __name__ == '__main__': 78 load_my_logging_cfg() 79 80 logging配置文件
1 """ 2 MyLogging Test 3 """ 4 5 import time 6 import logging 7 import my_logging # 导入自定义的logging配置 8 9 logger = logging.getLogger(__name__) # 生成logger实例 10 11 12 def demo(): 13 logger.debug("start range... time:{}".format(time.time())) 14 logger.info("中文测试开始。。。") 15 for i in range(10): 16 logger.debug("i:{}".format(i)) 17 time.sleep(0.2) 18 else: 19 logger.debug("over range... time:{}".format(time.time())) 20 logger.info("中文测试结束。。。") 21 22 if __name__ == "__main__": 23 my_logging.load_my_logging_cfg() # 在你程序文件的入口加载自定义logging配置 24 demo() 25 26 使用
1 注意注意注意: 2 3 4 #1、有了上述方式我们的好处是:所有与logging模块有关的配置都写到字典中就可以了,更加清晰,方便管理 5 6 7 #2、我们需要解决的问题是: 8 1、从字典加载配置:logging.config.dictConfig(settings.LOGGING_DIC) 9 10 2、拿到logger对象来产生日志 11 logger对象都是配置到字典的loggers 键对应的子字典中的 12 按照我们对logging模块的理解,要想获取某个东西都是通过名字,也就是key来获取的 13 于是我们要获取不同的logger对象就是 14 logger=logging.getLogger('loggers子字典的key名') 15 16 17 但问题是:如果我们想要不同logger名的logger对象都共用一段配置,那么肯定不能在loggers子字典中定义n个key 18 'loggers': { 19 'l1': { 20 'handlers': ['default', 'console'], # 21 'level': 'DEBUG', 22 'propagate': True, # 向上(更高level的logger)传递 23 }, 24 'l2: { 25 'handlers': ['default', 'console' ], 26 'level': 'DEBUG', 27 'propagate': False, # 向上(更高level的logger)传递 28 }, 29 'l3': { 30 'handlers': ['default', 'console'], # 31 'level': 'DEBUG', 32 'propagate': True, # 向上(更高level的logger)传递 33 }, 34 35 } 36 37 38 #我们的解决方式是,定义一个空的key 39 'loggers': { 40 '': { 41 'handlers': ['default', 'console'], 42 'level': 'DEBUG', 43 'propagate': True, 44 }, 45 46 } 47 48 这样我们再取logger对象时 49 logging.getLogger(__name__),不同的文件__name__不同,这保证了打印日志时标识信息不同,但是拿着该名字去loggers里找key名时却发现找不到,于是默认使用key=''的配置 50 51 !!!关于如何拿到logger对象的详细解释!!!
6.logger的继承(了解)
1 import logging 2 3 formatter=logging.Formatter('%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s', 4 datefmt='%Y-%m-%d %H:%M:%S %p',) 5 6 ch=logging.StreamHandler() 7 ch.setFormatter(formatter) 8 9 10 logger1=logging.getLogger('root') 11 logger2=logging.getLogger('root.child1') 12 logger3=logging.getLogger('root.child1.child2') 13 14 15 logger1.addHandler(ch) 16 logger2.addHandler(ch) 17 logger3.addHandler(ch) 18 logger1.setLevel(10) 19 logger2.setLevel(10) 20 logger3.setLevel(10) 21 22 logger1.debug('log1 debug') 23 logger2.debug('log2 debug') 24 logger3.debug('log3 debug') 25 ''' 26 2017-07-28 22:22:05 PM - root - DEBUG -test: log1 debug 27 2017-07-28 22:22:05 PM - root.child1 - DEBUG -test: log2 debug 28 2017-07-28 22:22:05 PM - root.child1 - DEBUG -test: log2 debug 29 2017-07-28 22:22:05 PM - root.child1.child2 - DEBUG -test: log3 debug 30 2017-07-28 22:22:05 PM - root.child1.child2 - DEBUG -test: log3 debug 31 2017-07-28 22:22:05 PM - root.child1.child2 - DEBUG -test: log3 debug 32 '''
七.json模块,pickle模块,都是对数据进行序列化操作:
之前我们学习过用eval内置方法可以将一个字符串转成python对象,不过,eval方法是有局限性的,对于普通的数据类型,json.loads和eval都能用,但遇到特殊类型的时候,eval就不管用了,所以eval的重点还是通常用来执行一个字符串表达式,并返回表达式的值。
1 import json 2 x="[null,true,false,1]" 3 print(eval(x)) #报错,无法解析null类型,而json就可以 4 print(json.loads(x))
系列化的概念:把一个变量(对象)从内存中变成一个可储存和传输的过程称为序列化。
为什么要序列化?
1:持久保存状态
需知一个软件/程序的执行就在处理一系列状态的变化,在编程语言中,'状态'会以各种各样有结构的数据类型(也可简单的理解为变量)的形式被保存在内存中。
内存是无法永久保存数据的,当程序运行了一段时间,我们断电或者重启程序,内存中关于这个程序的之前一段时间的数据(有结构)都被清空了。
在断电或重启程序之前将程序当前内存中所有的数据都保存下来(保存到文件中),以便于下次程序执行能够从文件中载入之前的数据,然后继续执行,这就是序列化。
具体的来说,你玩使命召唤闯到了第13关,你保存游戏状态,关机走人,下次再玩,还能从上次的位置开始继续闯关。或如,虚拟机状态的挂起等。
2:跨平台数据交互
序列化之后,不仅可以把序列化后的内容写入磁盘,还可以通过网络传输到别的机器上,如果收发的双方约定好实用一种序列化的格式,那么便打破了平台/语言差异化带来的限制,实现了跨平台数据交互。
反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickling。
如何序列化之json和pickle:
json
如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML,但更好的方法是序列化为JSON,因为JSON表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。JSON不仅是标准格式,并且比XML更快,而且可以直接在Web页面中读取,非常方便。
JSON表示的对象就是标准的JavaScript语言的对象,JSON和Python内置的数据类型对应如下:
import json d = {'name':'yuan','age':18,'phone':12333445111212215} print(type(d)) d1 = json.dumps(d) #序列化 转换为字符格式 print(type(d1)) f =open('a.txt','w') f.write(d1) f.close() d2=json.load(open('a.txt')) #反序列化 print(d2) s = '{"name":"iiiiiiii"}' #只要满足json格式的数据,无需dump也可以用load反序列化出来 f = open('a.txt','w') f.write(s) f.close() f = open('a.txt') d3 = json.loads(f.read()) print(d3) >>>>>>>>>> <class 'dict'> <class 'str'> {'age': 18, 'name': 'yuan', 'phone': 12333445111212215} {'name': 'iiiiiiii'}
pickle
1.pickle模块也是序列化模块:
与json的比较:优点:能够将任意格式的数据进行序列化,序列化的结果是转换成字节格式的数据
缺点:只能在python中的py文件之间进行序列,反序列化,而且python不同版本之间不兼容
import pickle 转换成字节格式 l = [1,2,3,4,5] l1 = pickle.dumps(l) print(l1) f = open('b.txt','wb') f.write(l1) #写入文件是不可见的数据格式,无法直接读取,必须反序列化才能看到数据内容 f.close() f1= open('b.txt','rb') p = pickle.loads(f1.read()) print(p) >>>>>>>>>>>>>>>>>. b'\x80\x03]q\x00(K\x01K\x02K\x03K\x04K\x05e.' [1, 2, 3, 4, 5]