小待

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 :: 管理 ::

Python学习第十篇:常用模块

一、时间模块 time

1.三种表达方式:

在Python中,通常有这几种方式来表示时间:

1. 时间戳(timestamp):(这个给程序用的,下面两个给人用)

通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。命令如下:

import time
print(time.time())  

输出

1496667277.8989

 

2. 格式化的时间字符串(Format String/String time):(分隔符号可以任意指定)

import time
print(time.strftime("%Y-%m-%d %X"))

输出

2017-06-05 20:55:48

 

python中时间日期格式化字符:

%y 两位数的年份表示(00-99)

%Y 四位数的年份表示(000-9999)

%m 月份(01-12)

%d 月内中的一天(0-31)

%H 24小时制小时数(0-23)

%I 12小时制小时数(01-12)

%M 分钟数(00=59)

%S 秒(00-59)

%a 本地简化星期名称

%A 本地完整星期名称

%b 本地简化的月份名称

%B 本地完整的月份名称

%c 本地相应的日期表示和时间表示

%j 年内的一天(001-366)

%p 本地A.M.或P.M.的等价符

%U 一年中的星期数(00-53)星期天为星期的开始

%w 星期(0-6),星期天为星期的开始

%W 一年中的星期数(00-53)星期一为星期的开始

%x 本地相应的日期表示

%X 本地相应的时间表示

%Z 当前时区的名称

%% %号本身

 

3. 结构化的时间(struct_time):时间元组

struct_time元组共有9个元素 :   (年,月,日,时,分,秒,一年中第几周,一年中第几天,夏令时)   -- 如 (2017, 6, 5, 22, 3, 38, 1, 48, 0)

分为本地时区的struct_time和UTC时区的struct_time

  • UTC世界标准时间,国际协调时间,简称UTC。不属于任意时区,中国大陆、中国香港、中国澳门、中国台湾、蒙古国、新加坡、马来西亚、菲律宾、西澳大利亚州的时间与UTC的时差均为+8,也就是UTC+8。

 

本地时间:

import time

print(time.localtime())

结果:(是一种对象的形式,可执行取需要的)
time.struct_time(tm_year=2017, tm_mon=11, tm_mday=2, tm_hour=11, tm_min=34, tm_sec=45, tm_wday=3, tm_yday=306, tm_isdst=0)

本地时间取年:

import  time

print(time.localtime().tm_year)

结果:
2017

 

UTC时间:(跟上面一样,只是一个是本地一个UTC)

import  time

print(time.gmtime())

结果:
time.struct_time(tm_year=2017, tm_mon=11, tm_mday=2, tm_hour=3, tm_min=39, tm_sec=45, tm_wday=3, tm_yday=306, tm_isdst=0)


UTC时间取年:
import  time

print(time.gmtime().tm_year)

结果:
2017

 

struct_time中一个元组里的9组数字:

对应的属性:

 

2.三种方式间互相转换

其中计算机认识的时间只能是'时间戳'格式(Timestamp),而程序员可处理的或者说人类能看懂的时间有: '格式化的时间字符串','结构化的时间' ,于是有了下图的转换关系:

 

具体如下:

  • time.localtime([secs])  --> 时间戳(timestamp)转结构化的时间(struct_time)

接收时间辍(指secs是时间戳)(1970纪元后经过的浮点秒数)并返回当地时间下的时间元组t

(t.tm_isdst可取0或1,取决于当地当时是不是夏令时)

import time
print(time.time())
print(time.localtime(1496669119.460393))
print(time.localtime(time.time()))

 输出

1496669128.140584
time.struct_time(tm_year=2017, tm_mon=6, tm_mday=5, tm_hour=21, tm_min=25, tm_sec=19, tm_wday=0, tm_yday=156, tm_isdst=0)
time.struct_time(tm_year=2017, tm_mon=11, tm_mday=2, tm_hour=15, tm_min=23, tm_sec=49, tm_wday=3, tm_yday=306, tm_isdst=0)

 

  • time.gmtime([secs])  --> 时间戳(timestamp)转 结构化的UTC时间(struct_time)

接收时间辍 并返回格林威治天文时间UTC下的时间元组t

(t.tm_isdst始终为0)

import time
print(time.time())
print(time.gmtime(1496669119.460393))
print(time.gmtime(time.time()))

输出

1496669289.290523

time.struct_time(tm_year=2017, tm_mon=6, tm_mday=5, tm_hour=13, tm_min=25, tm_sec=19, tm_wday=0, tm_yday=156, tm_isdst=0)
time.struct_time(tm_year=2017, tm_mon=11, tm_mday=2, tm_hour=7, tm_min=25, tm_sec=32, tm_wday=3, tm_yday=306, tm_isdst=0)

 

  • time.mktime(t)  --> 结构化的时间(struct_time) 转 时间戳(timestamp)

执行与gmtime(), localtime()相反的操作,接收struct_time对象作为参数,返回用秒数来表示(时间戳)时间的浮点数。

如果输入的值不是一个合法的时间,将触发 OverflowError 或 ValueError。

import time

t = (2017, 6, 5, 22, 3, 38, 1, 48, 0)
print (time.mktime(t))
print (time.mktime(time.localtime()))

输出

1496671418.0
1509606750.0

 

  • time.strftime(format,[tupletime])  --> 结构化的时间(struct_time) 转 格式化的时间字符串(Format string) ,tupletime表示时间元组

接收时间元组,返回时间字符串,格式由fmt决定。

import time

print(time.strftime('%Y %X',time.localtime()))
t = (2017, 6, 5, 22, 3, 38, 1, 48, 0)   #时间元组
print(time.strftime('%Y %X',t))
print(time.strftime('%Y %X',(2017,0,0,22,3,38,0,0,0)))

结果:

  2017 15:47:24
  2017 22:03:38 
  2017 22:03:38

 

  • time.strptime(str,fmt='%a %b %d %H:%M:%S %Y')  --> 格式化的时间字符串(Format string) 转 结构化的时间(struct_time)

根据fmt的格式接收时间字符串解析为时间元组。格式前后一一对应

import time
print (time.strptime("01 Nov 17", "%d %b %y")) #两位数年份
print(time.strptime("2017-06-01",'%Y-%m-%d'))   #四位数年份

输出

time.struct_time(tm_year=2017, tm_mon=11, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=335, tm_isdst=-1)
time.struct_time(tm_year=2017, tm_mon=6, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=152, tm_isdst=-1)

 

3. time.sleep(s)

推迟调用线程的运行,s指秒数。

import time

print ("Start : %s" % time.ctime())
time.sleep( 5 )
print ("End : %s" % time.ctime())

输出

Start : Mon Jun  5 21:45:13 2017
End : Mon Jun  5 21:45:18 2017

 

 

 

  • time.asctime([tupletime])  #tupletime是时间元组

接受时间元组并返回一个可读的形式为"Tue Dec 11 18:07:14 2008"(2008年12月11日 周二18时07分14秒)的24个字符的字符串。

import time
t = (2017, 6, 5, 22, 3, 38, 1, 48, 0)

print (time.asctime(t)
print (time.asctime(time.localtime()))
print (time.asctime())
print(time.asctime(time.localtime(1000000000.0)))

输出

Tue Jun  5 22:03:38 2017
Thu Nov  2 16:04:01 2017
Mon Jun 5 21:52:55 2017
Sun Sep  9 09:46:40 2001

 

  • time.ctime([secs])

接受时间戳并返回一个可读形式,相当于time.asctime(time.localtime(secs)),未给参数相当于asctime()

import time
print(time.ctime(1000000000.0))
print(time.ctime()) #不加参数等于print(time.asctime())

输出

Sun Sep  9 09:46:40 2001
Mon Jun 5 21:54:49 2017

 

二、random   随机从中取一个 值

  • 从一个序列中随机的抽取一个元素,可以使用 random.choice()
  • 为了提取出N个不同元素的样本用来做进一步的操作,可以使用 random.sample()
  • 如果你仅仅只是想打乱序列中元素的顺序,可以使用 random.shuffle()
  • 生成随机整数,请使用 random.randint()
  • 生成0到1范围内均匀分布的浮点数,使用 random.random()


例:

import random

print(random.random())        #大于0且小于1之间的小数
print(random.randint(1,3))    #大于等于1且小于等于3之间的整数
print(random.randrange(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的小数


item=[1,3,5,7,9]
random.shuffle(item) #打乱item的顺序,相当于"洗牌"
print(item)

输出

0.23127504367736695
1
2
[4, 5]
[1, '23']
2.202096727179022
[9, 5, 7, 1, 3]

 

应用:生成随机验证码

import random

def v_code(n):
    code = ''
    for i in range(n):
        num=random.randint(0,9)
        alf=chr(random.randint(65,90))
        add=random.choice([num,alf])
        code += str(add)
    return code

print(v_code(5))

输出

KDZSY

 

三、OS

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

os.access(path, mode)           # 检验权限模式   
os.chdir(path)                  # 改变当前工作目录
os.chflags(path, flags)         # 设置路径的标记为数字标记。
os.chmod(path, mode)            # 更改权限
os.chown(path, uid, gid)        # 更改文件所有者
os.chroot(path)                 # 改变当前进程的根目录
os.close(fd)                    # 关闭文件描述符 fd
os.closerange(fd_low, fd_high)  # 关闭所有文件描述符,从 fd_low (包含) 到 fd_high (不包含), 错误会忽略
os.curdir                       # 返回当前目录:('.')
os.dup(fd)                      # 复制文件描述符 fd
os.dup2(fd, fd2)                # 将一个文件描述符 fd 复制到另一个 fd2
os.environ                      # 获取系统环境变量
os.fchdir(fd)                   # 通过文件描述符改变当前工作目录
os.fchmod(fd, mode)             # 改变一个文件的访问权限,该文件由参数fd指定,参数mode是Unix下的文件访问权限。
os.fchown(fd, uid, gid)         # 修改一个文件的所有权,这个函数修改一个文件的用户ID和用户组ID,该文件由文件描述符fd指定。
os.fdatasync(fd)                # 强制将文件写入磁盘,该文件由文件描述符fd指定,但是不强制更新文件的状态信息。
os.fdopen(fd[, mode[, bufsize]])  # 通过文件描述符 fd 创建一个文件对象,并返回这个文件对象
os.fpathconf(fd, name)          # 返回一个打开的文件的系统配置信息。name为检索的系统配置的值,它也许是一个定义系统值的字符串,这些名字在很多标准中指定(POSIX.1, Unix 95, Unix 98, 和其它)。
os.fstat(fd)                    # 返回文件描述符fd的状态,像stat()。
os.fstatvfs(fd)                 # 返回包含文件描述符fd的文件的文件系统的信息,像 statvfs()
os.fsync(fd)                    # 强制将文件描述符为fd的文件写入硬盘。
os.ftruncate(fd, length)        # 裁剪文件描述符fd对应的文件, 所以它最大不能超过文件大小。
os.getcwd()                     # 返回当前工作目录
os.getcwdu()                    # 返回一个当前工作目录的Unicode对象
os.isatty(fd)                   # 如果文件描述符fd是打开的,同时与tty(-like)设备相连,则返回true, 否则False。
os.lchflags(path, flags)        # 设置路径的标记为数字标记,类似 chflags(),但是没有软链接
os.lchmod(path, mode)           # 修改连接文件权限
os.lchown(path, uid, gid)       # 更改文件所有者,类似 chown,但是不追踪链接。
os.link(src, dst)               # 创建硬链接,名为参数 dst,指向参数 src
os.listdir(path)                # 返回path指定的文件夹包含的文件或文件夹的名字的列表。
os.lseek(fd, pos, how)          # 设置文件描述符 fd当前位置为pos, how方式修改: SEEK_SET 或者 0 设置从文件开始的计算的pos; SEEK_CUR或者 1 则从当前位置计算; os.SEEK_END或者2则从文件尾部开始. 在unix,Windows中有效
os.lstat(path)                  # 像stat(),但是没有软链接
os.linesep                      # 当前平台使用的行终止符,win下为"\t\n",Linux下为"\n"
os.major(device)                # 从原始的设备号中提取设备major号码 (使用stat中的st_dev或者st_rdev field)。
os.makedev(major, minor)        # 以major和minor设备号组成一个原始设备号
os.makedirs(path[, mode])       # 递归文件夹创建函数。像mkdir(), 但创建的所有intermediate-level文件夹需要包含子文件夹。
os.minor(device)                # 从原始的设备号中提取设备minor号码 (使用stat中的st_dev或者st_rdev field )。
os.mkdir(path[, mode])          # 以数字mode的mode创建一个名为path的文件夹.默认的 mode 是 0777 (八进制)。
os.mkfifo(path[, mode])         # 创建命名管道,mode 为数字,默认为 0666 (八进制)
os.mknod(filename[, mode=0600, device])  # 创建一个名为filename文件系统节点(文件,设备特别文件或者命名pipe)。
os.path.normcase(path) #linux,mac原样返回;windows左斜杠变成反斜杠,大写成小写 os.open(file, flags[, mode]) # 打开一个文件,并且设置需要的打开选项,mode参数是可选的 os.openpty() # 打开一个新的伪终端对。返回 pty 和 tty的文件描述符。 os.pathconf(path, name) # 返回相关文件的系统配置信息。 os.pathsep # 用于分割文件路径的字符串 os.pardir # 获取当前目录的父目录字符串名:('..') os.pipe() # 创建一个管道. 返回一对文件描述符(r, w) 分别为读和写 os.popen(command[, mode[, bufsize]]) # 从一个 command 打开一个管道 os.path.abspath(path) # 返回path规范化的绝对路径,会以当前路径和另外写的的路径拼一个规范化的路径出来。 取执行脚本所在路径:os.path.abspath(__file__) os.path.split(path) # 将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.getctime(path)   # 返回path所指文件或目录的创建时间
os.path.getsize(path)   # 返回文件大小,如果文件不存在就返回错误

os.path.normcase(path) #linux,mac原样返回;windows左斜杠变成反斜杠,大写成小写
os.path.normpath(path) #规范路径,如把..转化成上一级实际目录
os.name # 字符串指示当前使用平台。win->'nt'; Linux->'posix'
os.read(fd, n) # 从文件描述符 fd 中读取最多 n 个字节,返回包含读取字节的字符串,文件描述符 fd对应文件已达到结尾, 返回一个空字符串。
os.readlink(path) # 返回软链接所指向的文件
os.remove(path) # 删除路径为path的文件。如果path 是一个文件夹,将抛出OSError; 查看下面的rmdir()删除一个 directory。
os.removedirs(path) # 递归删除目录。若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
os.rename(src, dst) # 重命名文件或目录,从 src 到 dst
os.renames(old, new) # 递归地对目录进行更名,也可以对文件进行更名。
os.rmdir(path) # 删除path指定的空目录,如果目录非空,则抛出一个OSError异常。
os.sep # 操作系统特定的路径分隔符,win下为"\\",Linux下为"/"
os.stat(path) # 获取path指定的路径的信息,功能等同于C API中的stat()系统调用。
os.stat_float_times([newvalue]) # 决定stat_result是否以float对象显示时间戳
os.statvfs(path) # 获取指定路径的文件系统统计信息
os.symlink(src, dst) # 创建一个软链接
os.system("bash command") # 运行shell命令,直接显示
os.tcgetpgrp(fd) # 返回与终端fd(一个由os.open()返回的打开的文件描述符)关联的进程组
os.tcsetpgrp(fd, pg) # 设置与终端fd(一个由os.open()返回的打开的文件描述符)关联的进程组为pg。
os.tempnam([dir[, prefix]]) # 返回唯一的路径名用于创建临时文件。
os.tmpfile() # 返回一个打开的模式为(w+b)的文件对象 .这文件对象没有文件夹入口,没有文件描述符,将会自动删除。
os.tmpnam() # 为创建一个临时文件返回一个唯一的路径
os.ttyname(fd) # 返回一个字符串,它表示与文件描述符fd 关联的终端设备。如果fd 没有与终端设备关联,则引发一个异常。
os.unlink(path) # 删除文件路径
os.utime(path, times) # 返回指定的path文件的访问和修改的时间。
os.walk(top[, topdown=True[, onerror=None[, followlinks=False]]]) # 输出在文件夹中的文件名通过在树中游走,向上或者向下。
os.write(fd, str) # 写入字符串到文件描述符 fd中. 返回实际写入的字符串长度

 

四、sys

sys模块用于提供对python解释器的相关操作。

 

 可以代替sys.argv

sys.argv           命令行参数List,第一个元素是程序本身路径,把命令含里面的参数转换成列表
sys.modules        返回系统导入的模块字段,key是模块名,value是模块
sys.exit(n)        退出程序,正常退出时exit(0)
sys.version        获取Python解释程序的版本信息
sys.maxint         最大的Int值
sys.path           返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform       返回操作系统平台名称
sys.stdout.write('please:')
val = sys.stdin.readline()[:-1]
sys.modules.keys() 返回所有已经导入的模块名
sys.modules.values() 返回所有已经导入的模块
sys.exc_info()     获取当前正在处理的异常类,exc_type、exc_value、exc_traceback当前处理的异常详细信息
sys.exit(n)        退出程序,正常退出时exit(0)
sys.hexversion     获取Python解释程序的版本值,16进制格式如:0x020403F0
sys.version        获取Python解释程序的
sys.api_version    解释器的C的API版本
sys.version_info
‘final’表示最终,也有’candidate’表示候选,serial表示版本级别,是否有后继的发行
sys.displayhook(value)      如果value非空,这个函数会把他输出到sys.stdout,并且将他保存进__builtin__._.指在python的交互式解释器里,’_’ 代表上次你输入得到的结果,hook是钩子的意思,将上次的结果钩过来
sys.getdefaultencoding()    返回当前你所用的默认的字符编码格式
sys.getfilesystemencoding() 返回将Unicode文件名转换成系统文件名的编码的名字
sys.setdefaultencoding(name)用来设置当前默认的字符编码,如果name和任何一个可用的编码都不匹配,抛出 LookupError,这个函数只会被site模块的sitecustomize使用,一旦别site模块使用了,他会从sys模块移除
sys.builtin_module_names    Python解释器导入的模块列表
sys.executable              Python解释程序路径
sys.getwindowsversion()     获取Windows的版本
sys.copyright      记录python版权相关的东西
sys.byteorder      本地字节规则的指示器,big-endian平台的值是’big’,little-endian平台的值是’little’
sys.exc_clear()    用来清除当前线程所出现的当前的或最近的错误信息
sys.exec_prefix    返回平台独立的python文件安装的位置
sys.stderr         错误输出
sys.stdin          标准输入
sys.stdout         标准输出
sys.platform       返回操作系统平台名称
sys.path           返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.maxunicode     最大的Unicode值
sys.maxint         最大的Int值
sys.version        获取Python解释程序的版本信息
sys.hexversion     获取Python解释程序的版本值,16进制格式如:0x020403F0

 

进度条(注意:在pycharm中执行无效,请到命令行中以脚本的方式执行)

import sys,time

for i in range(50):
    sys.stdout.write('%s\r' %('#'*i))
    sys.stdout.flush()
    time.sleep(0.1)

 

五、shutil

高级的文件、文件夹、压缩包处理模块;拷贝压缩等

 

1. shutil.copyfileobj(fsrc, fdst[, length])

将文件内容拷贝到另一个文件中

import shutil
shutil.copyfileobj(open('old.xml','r'), open('new.xml', 'w'))

 

2.shutil.copyfile(src, dst)

拷贝文件

shutil.copyfile('f1.log', 'f2.log') #目标文件无需存在

 

3. shutil.copymode(src, dst)

仅拷贝权限。内容、组、用户均不变

shutil.copymode('f1.log', 'f2.log') #目标文件必须存在

 

4. shutil.copystat(src, dst)

仅拷贝状态的信息,包括:mode bits, atime, mtime, flags

shutil.copystat('f1.log', 'f2.log') #目标文件必须存在

 

5 .shutil.copy(src, dst)

拷贝文件和权限

import shutil
shutil.copy('f1.log', 'f2.log')

 

6. shutil.copy2(src, dst)

拷贝文件和状态信息

import shutil  
shutil.copy2('f1.log', 'f2.log')

 

7. shutil.ignore_patterns(*patterns)

    shutil.copytree(src, dst, symlinks=False, ignore=None)

递归的去拷贝文件夹

import shutil
shutil.copytree('folder1', 'folder2', ignore=shutil.ignore_patterns('*.pyc', 'tmp*')) #目标目录不能存在,注意对folder2目录父级目录要有可写权限,ignore的意思是排除 

 

8. shutil.rmtree(path[, ignore_errors[, onerror]])

递归的去删除文件

import shutil
shutil.rmtree('folder1')

 

9. shutil.move(src, dst)

递归的去移动文件,它类似mv命令,其实就是重命名

import shutil
shutil.move('folder1', 'folder3')

 

10. shutil.make_archive(base_name, format,root_dir)

压缩并返回文件路径(zip、tar)-----> 解压需要zipfile或tarfile

 
base_name: 压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径,如
data_bak => 保存至当前路径 /tmp/data_bak => 保存至/tmp/下 format: 压缩包种类,“zip”, “tar”, “bztar”,“gztar” root_dir: 要压缩的文件夹路径(默认当前目录) owner: 用户,默认当前用户 group: 组,默认当前组 logger: 用于记录日志,通常是logging.Logger对象
#将 /data 下的文件打包放置当前程序目录
import shutil
ret = shutil.make_archive("data_bak", 'gztar', root_dir='/data')
  
  
#将 /data下的文件打包放置 /tmp/目录
import shutil
ret = shutil.make_archive("/tmp/data_bak", 'gztar', root_dir='/data')

 

shutil 对压缩包的处理是调用 ZipFile 和 TarFile 两个模块来进行的,详细:

  • zipfile压缩解压缩
import zipfile

# 压缩
z = zipfile.ZipFile('laxi.zip', 'w')
z.write('a.log')
z.write('data.data')
z.close()

# 解压
z = zipfile.ZipFile('laxi.zip', 'r')
z.extractall(path='.')
z.close()

 

  • tarfile压缩解压缩
import tarfile
#arcname 给被压缩的文件起别名同时也就删除了路径,避免把所在路径都压缩了
# 压缩
>>> t=tarfile.open('/tmp/egon.tar','w')
>>> t.add('/test1/a.py',arcname='a.bak')
>>> t.add('/test1/b.py',arcname='b.bak')
>>> t.close()


# 解压
>>> t=tarfile.open('/tmp/egon.tar','r')
>>> t.extractall('/egon')
>>> t.close()

 

 六、json&pickle (序列化)

 pickle只能pyhon使用,跨不了平台    ,shelve跟pickle类似

1.序列化定义

把对象(变量)从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling,在其他语言中也被称之为serialization,marshalling,flattening等等,都是一个意思。

 

2.序列化的好处(为什么要序列化)

  • 持久保存状态

需知一个软件/程序的执行就在处理一系列状态的变化,在编程语言中,'状态'会以各种各样有结构的数据类型(也可简单的理解为变量)的形式被保存在内存中。

内存是无法永久保存数据的,当程序运行了一段时间,我们断电或者重启程序,内存中关于这个程序的之前一段时间的数据(有结构)都被清空了。

在断电或重启程序之前将程序当前内存中所有的数据都保存下来(保存到文件中),以便于下次程序执行能够从文件中载入之前的数据,然后继续执行,这就是序列化。

具体的来说,你玩使命召唤闯到了第13关,你保存游戏状态,关机走人,下次再玩,还能从上次的位置开始继续闯关。或如,虚拟机状态的挂起等。

  • 跨平台数据交互

序列化之后,不仅可以把序列化后的内容写入磁盘,还可以通过网络传输到别的机器上,如果收发的双方约定好实用一种序列化的格式,那么便打破了平台/语言差异化带来的限制,实现了跨平台数据交互。

反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickling。

 

3.json

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

json模块主要用于处理json格式的数据,可以将json格式的数据转化为python的字典,便于python处理,同时也可以将python的字典或列表等对象转化为json格式的数据,便于跨平台或跨语言进行数据交互。

 

    JSON和Python内置的数据类型对应如下:

  • Python 编码为 JSON 类型转换对应表:

  • JSON 解码为 Python 类型转换对应表:

 

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

1. dumps 和 loads 用于python对象和字符串间的序列化和反序列化

dumps:   将python 基本数据类型转化为json格式数据类型

d1 = {'key2':'value2'}
d2 = json.dumps(d1)

print(d1,type(d1))
print(d2,type(d2))

结果:
{'key2': 'value2'} <class 'dict'>
{"key2": "value2"} <class 'str'>       #经dumps处理之后,dict变为str
 

 

loads:   将json转化为python数据类型

import json

s1 = '{"key1":"value1"}'      #字符串只能是这个格式的,才能被json转换  ---> 通过loads进行反序列化时,必须使用双引号
s2 = json.loads(s1)           #使用loads反序列化

print(s1,type(s1))
print(s2,type(s2))
结果:
{"key1":"value1"} <class 'str'>
{'key1': 'value1'} <class 'dict'> #经loads处理之后,str变为dict

 

2. dump 和load 用于文件的序列化和反序列化    ---> 这样更简单。直接序列化文件

dump:主要用于json文件的读写,

             json.dump(x,f)    --->  x是对象,f是一个文件对象,这样将json字符串写入到文本文件中

import json

d1 = {'key2':'value2'}
json.dump(d1,open('序列化.json','w')) #将d1序列化,并写入文件

 

load:加载json文件,json格式,反序列化

import json

e1 = json.load(open('序列化.json','r')) #读取json文件,反序列化
print(e1,type(e1))

结果:
{'key2': 'value2'} <class 'dict'> #文件反序列化load还原成字典

 

注意:

1. json 不认单引号,里面需要用双引号;

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

 

4.pickle  ---> 与json相似,但需要使用二进制方式读取文件 (rb wb)

pickle模块实现了基本的数据序列和反序列化,和json的功能类似。
通过pickle模块的序列化操作我们能够将程序中运行的对象信息保存到文件中去,永久存储,也可以简单的将字符进行序列化
通过pickle模块的反序列化操作,我们能够从文件中创建上一次程序保存的对象,也可以将字符进行反序列化。

和json不同的是:

                  json   更适合跨语言 可以处理字符串,基本数据类型;

                  pickle python专有,更适合处理复杂类型的序列化,可以序列化python任意的对象

 

注意: pickle虽然可以序列化函数,然后在同一脚本里直接反序列化可以执行这个函数。但若是在不同的文件中反序列化在执行会报错。因为序列化的内存地址指向的已被释放

 

  • pikle模块提供 dumps loads dump load四个基本功能
  • dumps 和loads 用于python对象和字符串间的序列化和反序列化

dumps 和json.dumps功能一样,但是以字节对象形式返回封装的对象
loads和json.loads功能一样,从字节对象中读取被封装的对象,并返回

复制代码
import pickle

s1 = '{"key1":"value1"}'      #字符串只能是这个格式的,才能被转换   通过loads进行反序列化时,必须使用双引号

d1 = {'key2':'value2'}

s3 = pickle.dumps(s1)
print('s1的内容:',s1)
print("s1的类型:",type(s1))
print('s3的内容:',s3)
print("s3的类型:",type(s3))

d3 = pickle.loads(s3)
print('d1的内容:',d1)
print("d1的类型:",type(d1))
print('d3的内容:',d3)
print("d3的类型",type(d3))
复制代码

输出

复制代码
s1的内容: {"key1":"value1"}
s1的类型: <class 'str'>
s3的内容: b'\x80\x03X\x11\x00\x00\x00{"key1":"value1"}q\x00.'
s3的类型: <class 'bytes'>   #dumps处理之后返回的是字节类型
d1的内容: {'key2': 'value2'}
d1的类型: <class 'dict'>
d3的内容: {"key1":"value1"}
d3的类型 <class 'str'>
复制代码

 

 

  • dump 和load 用于对文件进行序列化和反序列化.python数据持久化用的比较多

 

pickle.dump(obj, file, [,protocol])

注解:将对象obj保存到文件file中去。
  protocol为序列化使用的协议版本,0:ASCII协议,所序列化的对象使用可打印的ASCII码表示;
  1:老式的二进制协议;
  2:2.3版本引入的新二进制协议,较以前的更高效。其中协议0和1兼容老版本的python。protocol默认值为0。   
  file:对象保存到的类文件对象。file必须有write()接口, file可以是一个以'w'方式打开的文件或者一个StringIO对象或者其他任何实现write()接口的对象。如果protocol>=1,文件对象需要是二进制模式打开的。

pickle.load(file)   

注解:从file中读取一个字符串,并将它重构为原来的python对象。   

file:类文件对象,有read()和readline()接口
复制代码
import pickle

s1 = '{"key1":"value1"}'      #字符串只能是这个格式的,才能被json转换   通过loads进行反序列化时,必须使用双引号

d1 = {'key2':'value2'}

pickle.dump(s1,open('序列化.txt','wb'))     #注意需使用二进制方式写入文件
e2 = pickle.load(open('序列化.txt','rb'))   #需使用二进制方式读取文件
print("e2的类型:",type(e2))
print('e2的内容:',e2)
复制代码

输出

e2的类型: <class 'str'>
e2的内容: {"key1":"value1"}

 

七、shelve (序列化)

 shelve模块比pickle模块简单,只有一个open函数,返回类似字典的对象,可读可写。

 key必须为字符串,而值可以是python所支持的数据类型。

import shelve

f=shelve.open('sheve.txt')
f['student1']={'name':'egon','age':18,'height':'180cm'}
print(f['student1']['name']) f.close()

八、xml (解析)

xml是实现不同语言或程序之间进行数据交换的协议,可扩展标记语言,标准通用标记语言的子集。是一种用于标记电子文件使其具有结构性的标记语言。

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

<?xml version="1.0"?>
<data>
    <country name="Liechtenstein">
        <rank updated="yes">2</rank>
        <year>2008</year>
        <gdppc>141100</gdppc>
        <neighbor name="Austria" direction="E"/>
        <neighbor name="Switzerland" direction="W"/>
    </country>
    <country name="Singapore">
        <rank updated="yes">5</rank>
        <year>2011</year>
        <gdppc>59900</gdppc>
        <neighbor name="Malaysia" direction="N"/>
    </country>
    <country name="Panama">
        <rank updated="yes">69</rank>
        <year>2011</year>
        <gdppc>13600</gdppc>
        <neighbor name="Costa Rica" direction="W"/>
        <neighbor name="Colombia" direction="E"/>
    </country>
</data>

xml数据

 

 new_xml=ET.Element('namelist')     #Element  初始化一个namelist节点,获取一个对象new_xml
 s_xml = ET.SubElement(new_xml, "name_s", attrib={"enrolled": "yes"})  #SubElement 在new_xml中初始化一个子节点name_s,属性为。。

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

print(root.iter('year'))       #全文搜索name为year的
print(root.find('country'))    #在root的子节点找,只找一个
print(root.findall('country')) #在root的子节点找,找所有

 

 2. i.tag:标签      i.text:内容     i.attrib:属性

iter  迭代器

import xml.etree.ElementTree as ET

tree = ET.parse("a")                 #有的
root = tree.getroot()                #有的

for i in root.iter('year'):          #root.iter('year')是全文寻找,但其是个迭代器
print(i.tag,i.text,i.attrib)

结果:
year 2009 {'update': 'yes'}
year 2012 {'update': 'yes'}
year 2012 {'update': 'yes'}

find(findall)

print(root.find('country'))   #找到一个
print(root.find('country').attrib)  #显示属性,为字典结构

结果:
<Element 'country' at 0x0000025798A172C8>
{'name': 'Liechtenstein'}

   

import xml.etree.ElementTree as ET
 
tree = ET.parse("xmltest.xml")   #有的
root = tree.getroot()            #有的 
#print(root.tag)
 
#遍历xml文档
for child in root:
    print('========>',child.tag,child.attrib,child.attrib['name'])
    for i in child:
        print(i.tag,i.attrib,i.text)
#只遍历year 节点 for node in root.iter('year'): print(node.tag,node.text) #修改 for node in root.iter('year'): new_year=int(node.text)+1 node.text=str(new_year)
#增加 属性 node.set('updated','yes') #这儿set的是属性 node.set('version','1.0') tree.write('test.xml') #修改后只是到内存里了,需要保存。通过tree
#删除 节点
#删除root下的country:
for country in root.findall('country'): rank = int(country.find('rank').text) if rank > 50: root.remove(country)
tree.write('output.xml')
#删除country下的year:
for country in root:
# print(country)
# print('===>',country.find('year'))
year=country.find('year')
if int(year.text) > 2010:
country.remove(year)

tree.write('output2.xml')
#增加节点 
在country内添加(append)节点year2
import xml.etree.ElementTree as ET tree = ET.parse("a.xml") root=tree.getroot()

#在大于2010年的标签后面再加一个标签 for country in root.findall('country'): for year in country.findall('year'): if int(year.text) > 2000: year2=ET.Element('year2') #初始化一个year2 year2.text='新年' #year2加内容 year2.attrib={'update':'yes'} #加属性 ---> 这儿增加属性,字典形式 country.append(year2) #往country节点下添加year2子节点 tree.write('b.xml') #保存

 

创建xml文档:

import xml.etree.ElementTree as ET
 
 
new_xml = ET.Element("namelist")                               #生成名叫namelist的子节点
name = ET.SubElement(new_xml,"name",attrib={"enrolled":"yes"}) #在namelist下生成名叫name的子节点
age = ET.SubElement(name,"age",attrib={"checked":"no"})
sex = ET.SubElement(name,"sex")
sex.text = '33'
name2 = ET.SubElement(new_xml,"name",attrib={"enrolled":"no"})
age = ET.SubElement(name2,"age")
age.text = '19'
 
et = ET.ElementTree(new_xml)                                    #生成文档对象
et.write("test.xml", encoding="utf-8",xml_declaration=True)     #写到文件去,最后声明是xml格式
 
#ET.dump(new_xml)                #打印生成的

 

九、configparser

configparser用于配置文件解析,可以解析特定格式的配置文件,多数此类配置文件名格式为XXX.ini,例如mysql的配置文件。

配置文件如下:

a.cfg ----> key value形式

[section1]
k1 = v1
k2:v2
user=egon
age=18
is_admin=true
salary=31

[section2]
k1 = v1

读取:

import configparser

config=configparser.ConfigParser()    #准备,有的
config.read('a.cfg')                  #开始读文件

#sections 查看所有的标题
res=config.sections()                 #['section1', 'section2']
print(res)

#options 查看标题section1下所有key value的key  
options=config.options('section1')
print(options)                        #['k1', 'k2', 'user', 'age', 'is_admin', 'salary']

#items 查看标题section1下所有key value的(key,value)格式
item_list=config.items('section1')
print(item_list)                      #[('k1', 'v1'), ('k2', 'v2'), ('user', 'egon'), ('age', '18'), ('is_admin', 'true'), ('salary', '31')]

#get 查看标题section1下user的值 (字符串格式)
val=config.get('section1','user')
print(val)                            #egon

#getint 查看标题section1下age的值 (整数格式)
val1=config.getint('section1','age')
print(val1)                           #18

#getboolean 查看标题section1下is_admin的值 (布尔值格式)
val2=config.getboolean('section1','is_admin')
print(val2)                          #True

#getfloat 查看标题section1下salary的值 (浮点型格式)
val3=config.getfloat('section1','salary')
print(val3)                         #31.0

修改

import configparser

config=configparser.ConfigParser()
config.read('a.cfg')


#remove_section 删除整个标题section2
config.remove_section('section2')

#remove_option 删除标题section1下的某个k1和k2
config.remove_option('section1','k1')
config.remove_option('section1','k2')  #不存在会报错

#has_section 判断是否存在某个标题
print(config.has_section('section1'))

#has_option 判断标题section1下是否有user
print(config.has_option('section1',''))


#add_section添加一个标题
config.add_section('egon')

#set 在标题egon下添加name=egon,age=18的配置
config.set('egon','name','egon')
config.set('egon','age',18)              #报错,必须是字符串'18'

#write 最后将修改的内容写入文件,完成最终的修改 ---> 改在内存,需要写到文件 config.write(open('a.cfg','w'))



config=configparser.ConfigParser()
config.read('a.cfg')
print(type(config.getint('egon','age'))) #虽然写入是以字符串类型,但还是可以int

 

十、hashlib

用于加密相关的操作,代替了md5模块和sha模块,主要提供SHA1,SHA224,SHA256,SHA384,SHA512,MD5算法。
在python3中已经废弃了md5和sha模块。

摘要算法又称为哈希算法,散列算法。它通过一个函数,把任意长度的数据转换为一个长度固顶的数据串(通常用16进制的字符串表示)用于加密相关的操作。

MD5 算法 三个特点:

1.内容相同则hash运算结果相同,内容稍微改变则hash值则变;
2.不可逆推;
3.相同算法:无论校验多长的数据,得到的哈希值长度固定。

 

  • md5加密

import hashlib
hash = hashlib.md5()
hash.update('admin'.encode('utf-8'))  #需要bytes形式
print(hash.hexdigest())               #这样才输出了加密后信息

结果:
21232f297a57a5a743894a0e4a801fc3

  每次update都加入了新的信息进去,拼成新的,所以结果不一样:

import hashlib

m=hashlib.md5()
b=hashlib.md5()

b.update('11111'.encode('utf-8'))
b.update('11111'.encode('utf-8')) #多一次update
print(b.hexdigest())

m.update('11111'.encode('utf-8'))
print(m.hexdigest())

结果:
e11170b8cbd2d74102651cb967fa28e5
b0baee9d279d34fa1dfd71aadb908c3f
  • sha256加密

import hashlib
hash = hashlib.sha256()
hash.update('admin'.encode('utf-8'))
print(hash.hexdigest())

结果:
8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918

 

以上加密算法虽然很厉害,但仍然存在缺陷,通过撞库可以反解。所以必要对加密算法中添加自定义key再来做加密。

  • ‘加盐’加密  (md5加盐)

import hashlib

hash = hashlib.md5('exin'.encode('utf-8')) #加盐,原本有值
# hash = hashlib.md5()
# hash.update('exin'.encode('utf-8')) #这种结果也一样
hash.update('admin'.encode('utf-8')) #再增加
print(hash.hexdigest())
  • hmac加密 (也加盐)

hmac内部对我们创建的key和内容进行处理后在加密

import hmac
h = hmac.new('python'.encode('utf-8'))
h.update('helloworld'.encode('utf-8'))
print(h.hexdigest())

结果:
b3b867248bb4cace835b59562c39fd55

 

十一、suprocess

subprocess最早在2.4版本引入。

用来生成子进程,并可以通过管道连接他们的输入/输出/错误,以及获得他们的返回值。

subprocess提供了一些管理标准流(standard stream)和管道(pipe)的工具,从而在进程间使用文本通信。

#标准输出
res=subprocess.Popen(r'ls /Users/jieli/Desktop',shell=True,stdout=subprocess.PIPE) #stdout标准正确输出,扔到管道,不加这个就扔到终端了 print(res.stdout.read().decode('utf-8')) #拿到输出,bytes结果,需要decode。以当前系统为编码

 

#正确和错误都输出
import subprocess res=subprocess.Popen('diasdfasdfr',shell=True, stderr=subprocess.PIPE, #stderr stdout=subprocess.PIPE) print(res.stdout.read().decode('gbk')) print(res.stderr.read().decode('gbk'))

  

模拟过滤:

'''
sh-3.2# ls /Users/egon/Desktop |grep txt$ mysql.txt tt.txt '''
import  subprocess

#1.
##### 一个数据流可以和另外一个数据流交互 ---> 输入输出管道通信,管道里只能取一次
res1=subprocess.Popen('ls /Users/jieli/Desktop',shell=True,stdout=subprocess.PIPE) #stdout标准正确输出,扔到管道,不加这个就扔到终端了
res=subprocess.Popen('grep txt$',shell=True,stdin=res1.stdout,stdout=subprocess.PIPE) #stdin指定res1的stdout为输入来源
print(res.stdout.read().decode('utf-8'))

#2.
##### 等同于上面,但是上面的优势在于,一个数据流可以和另外一个数据流交互,可以通过爬虫得到结果然后交给grep
res1=subprocess.Popen('ls /Users/jieli/Desktop |grep txt$',shell=True,stdout=subprocess.PIPE)
print(res1.stdout.read().decode('utf-8')) #拿到输出,bytes结果,需要decode。以当前系统为编码 #3. #### windows下: # dir | findstr 'test*' # dir | findstr 'txt$'
import subprocess
res1=subprocess.Popen(r'dir C:\Users\Administrator\PycharmProjects\test\函数备课',shell=True,stdout=subprocess.PIPE) res=subprocess.Popen('findstr test*',shell=True,stdin=res1.stdout,stdout=subprocess.PIPE) print(res.stdout.read().decode('gbk')) #subprocess使用当前系统默认编码,得到结果为bytes类型,在windows下需要用gbk解码

 详细参考官网:https://docs.python.org/2/library/subprocess.html?highlight=subprocess#frequently-used-arguments

十二、logging

用于便捷记录日志且线程安全的模块

 

import logging

logging.basicConfig(filename='access.log', format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S %p', level=10)
#1. logging.debug('debug') logging.info('info') logging.warning('warning') logging.error('error111') logging.critical('critical')

#2. logging.log(40,'log11') #如果level=40,则只有logging.critical和loggin.error的日志会被打印
一:如果不指定filename,则默认打印到终端
二:指定日志级别: 指定方式: 1:level=10 2:level=logging.ERROR 日志级别种类: CRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0 三:指定日志级别为ERROR,则只有ERROR及其以上级别的日志会被打印

 

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

 

  • 日志格式

posted on 2017-06-10 11:29  小待  阅读(243)  评论(0)    收藏  举报