Python第六课----IO和序列化
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python第六课----IO和序列化相关的知识,希望对你有一定的参考价值。
一、文件IO常用操作
1、open打开、read读取、write写入、close关闭、readline行读取、readlines多行读取、seek文件指针操作、tell指针位置
2、open(file,mode="r",buffering=-1,encoding=None,errors=None,newline=None,closefd=True,opener=None)
3、encoding=‘cp936‘/‘utf-8’,一个是windows下的,一个linux下的
4、open的参数:
1、file----打开或要创建的文件,如果不指定路径,默认是当前路径
2、mode(模式) 1、r,缺省的,表示只读打开,不写则r 2、w,只写打开----如果文件在,则覆盖之前内容,如果文件不存在,则创建文件 3、x,创建并写入一个新文件只写打开,原来有则创建失败 4、a,写入打开,原来有则追加 5、b,二进制模式,rb,wb 6、t,缺省的,文本模式 7、+读写打开一个文件,将缺少的权限补上,r+,w+,x+,a+
3、mode=r指针起始在0 mode=a指针起始在EOF,end of file tell()显示指针现在的位置 seek(offset[,whence])移动指针位置,offset偏移多少字节,whence表示从哪里开始
4、文本模式下: 1、whence=0,缺省值,表示从头开始,offset只能接受正整数 2、whence=1,表示从当前位置,offset只接受0 3、whence=2,表示从EOF位置,offset只接受0
5、二进制模式下: 1、whence=0,缺省值,表示从头开始,offset只能是正整数 2、whence=1,表示从当前位置,offset可正可负 3、whence=2,表示从EOF位置,offset可正可负 4、向前的负数,不可超界
5、buffering:缓冲区
1、-1表示使用缺省大小,如果是二进制模式,使用io.DEFAULT_BUFFER_SIZE值,一般4096或8192
2、文本模式,如果是终端,是行缓存,不是的话,按照二进制的缓存模式
3、参数含义 1、0只在二进制模式下使用,表示关闭buffer 2、1只在文本模式使用,表示使用行缓冲,见到换行符就flush 3、大于1用于指定buffersize,但是文本模式没什么用
4、flush()将缓冲区数据写入磁盘,close()关闭前会flush一下
5、写法 import io f = open(‘text‘,‘w+b‘,16) print(io.DEFAULT_BUFFER_SIZE) f.write(‘magedu.com‘.encode()) f.seek(0) f.write(‘www.magedu.com‘.encode()) f.flush() f.close()
6、文本模式行缓冲 f = open(‘text‘,‘w+‘,1) f.write(‘mag‘) f.write(‘mag‘*4) f.write(‘\n‘) f.write(‘edu‘) f.seek(0) f.read() f.close()
7、无缓存的二进制文件,FIFO文件 f = open(‘text‘,‘w+b‘,0) f.write(b‘m‘) f.write(b‘a‘) f.write(b‘g‘) f.write(‘magedu‘.encode()*4) f.write(b‘\n‘) f.write(b‘Hello\nPython‘)
6、文本模式,一般都用默认缓存大小 二进制模式,是一个个字节的操作,可以指定buffer大小 一般来说,默认缓冲大小是最好的选择 一般编程中,需要写磁盘,调用flush(),不需要则在自动flush时或close()时
7、其他参数 1、errors:什么样的编码错误将被捕获:None和strict表示有编码错误将抛出ValueError错误,ignore表示忽略 2、newline:文本模式中,换行的转换,可以为None,"、","\r","\n","\r\n"读时,None表示上面符号都变成"\n",表示不会自动转换通用换行符,其他合法字符表示换行符就是指定字符,按照指定字符分行写时,None表示"\n"都会被替换为系统缺省行分隔符"os.linesep","\n"或""表示"\n"不替换,其他合法字符表示"\n"会被替换成指定字符 3、closefd:关闭文件秒数符,True表示关闭,False表示在close后还保持这个秒数符
8、read(size=-1) read表示读取多少字符或字节,负数或None表示全部读取
9、readline(size=-1) 一行行读取文件内容,size设置一次能读取行内几个字符或字节。
10、readlines(hint=-1) 读取所有行的列表,指定hit返回指定的行数
11、其他: 1、seekable()是否可seek 2、readable()是否可读 3、writable()是否可写 4、closed是否已关闭
12、上下文管理
1、使用finally来关闭文件 f = open(‘test‘,‘r+‘) try: f.write(‘abc‘) finally: f.close() print(f.closed)
2、使用with as关键字 with open(‘test‘) as f: f.write(‘abc‘) print(f.closed)
3、f = open(‘test‘,‘r+‘) with f: f.write(‘abc) print(f.closed)
二、StringIO
1、io模块中的类,在内存中开辟一个文本模式的buffer,可以像文件对象一样操作,close则关闭,内存足够少落地,提高效率
from io import StringIO sio = StringIO() print(sio.readable(),sio.seekable(),sio.writable()) sio.write(‘magedu\nPython‘) sio.seek(0) print(sio.readline()) sio.seek(0) print(sio.readlines()) print(sio.getvalue()) sio.close() print(sio.closed)
2、getvalue()
获得全部内容,跟指针没有关系
三、BytesIO
1、io模块中的类,开辟二进制的buffer,操作与StringIO类 from io import BytesIO bio = BytesIO() print(bio.readable(),bio.writable(),bio.seekable()) bio.write(b‘magedu\nPython‘) bio.seek(0) print(bio.readline()) print(bio.getvalue()) bio.close() print(bio.closed)
四、file-like对象
1、类文件对象,可以像文件对象一样操作
2、socket对象、输入输出对象(stdin、stdout)都是类文件对象 from sys import stdout from sys import stdin f = stdout print(type(f)) print(f.write(‘abc‘)) stdin不能写,stdout不能读
五、路径操作
1、路径操作模块
3.4版本之前 1、os.path模块 from os import path p = path.join(‘/etc‘,‘sysconfig‘,‘network‘) print(type(p),p) print(path.exists(p)) print(path.split(p)) #取*head,tail print(path.abspath(‘.‘)) #绝对路径,当前工作路径,"."是当前路径 p = path.join(‘o:/‘,p,‘test.txt‘) print(path.dirname(p)) #当前路径 print(path.basename(p)) #basename print(path.splitdrive(p)) #驱动器
3.4版本之后 2、pathlib模块 from pathlib import Path p = Path() print(type(p)) # windows和Linux不同 print(p) # ‘.‘,两个系统一样 print(p.absolute()) # 不同 p = p.joinpath(‘a‘,‘b‘) # 路径操作 print(p) print(p.absolute()) p = p/‘c‘/‘d‘ # 可以直接操作路径 p/=‘e‘‘/‘‘f‘ # /=类似于+= print(p) p1 = Path(‘/etc‘) # 从根开始,绝对路径 print(p1) print(p1.absolute()) # p2 = ‘/etc‘/‘sysconfig‘ 字符串拼接,p2不在,不能直接操作 p2 = Path(‘.‘) p2 = p2 / ‘/etc/‘ / ‘sysconfig‘ # /etc,强行从根开始 p3 = Path(‘a‘,‘b‘,‘c‘) print(p2) print(p2.parts) # 拿属性,生成元组,方便迭代 p4 = p2.joinpath(‘a‘,‘b‘,‘c‘) print(p4) print(str(p4),‘\n‘,bytes(p4)) # 路径字符串 print(p4.parent) print(p4.parent.parent) print(p4.parents) # 可迭代对象 print(list(p4.parents)) # 最亲的开始 print(list(p4.parents)[0]) # 取第一个 print(next(iter(p4.parents))) # list不可迭代,换成iter,a = iter(p4.parents)---->next(a) p5 = Path() print(list(p5.absolute().parents)) # p5是空的,用绝对路径包一下
3、属性操作 from pathlib import Path p = Path(‘a‘,‘b‘,‘c‘,‘d‘) p /= ‘e‘‘/‘‘f‘ p = p.joinpath(‘xx.ifg‘) p1 = Path(str(p) + ‘.gz‘) print(p1) print(p.name) # 目录的最后一部分,全部 print(p.stem) # 目录的最后一个部分,没有后缀名 print(p.suffix) # 目录的最后一部分的扩展名 print(p1.suffixes) # 返回多个扩展名列表 print(p1.with_suffix(‘.rgz‘)) # 替换扩展名 print(p1.with_name(‘test.tgz‘)) # 替换name print(p1.parent/‘test.tgz‘) # 同上
4、命令 from pathlib import Path p = Path() p = p/‘/a‘/‘b‘/‘c‘ print(p.cwd()) # 当前工作路径,与描述的路径无关 print(p.home()) # 当前home,与其他无关 print(p.is_dir()) # 当前描述的路径是不是目录,不过目前没有,所以False print(p.is_file()) # 同上,不存在则False print(p.is_symlink()) # 软连接 print(p.is_socket()) # socket文件 print(p.is_block_device()) # 块设备 print(p.is_char_device()) # 字符设备 print(p.is_absolute()) # 绝对路径 # print(p.resolve()) # 返回一个新路径,是当前Path对象的绝对路径,如果是软连接,则被解析,但不存在的话,则报错 # 临时可以用absolute,推荐使用resolve print(p.exists()) # p.rmdir() # 删除空目录 p1 = Path(‘‘) p1 /= p1/‘D:/‘/‘QQLive‘/‘mysql.tar.gz‘ p1 = p1.with_name(‘test.txt‘) p1.touch() #创建 print(p1.resolve())
5、
print(p1.as_uri()) # 生成url p2.mkdir() #创建目录,p2.mkdir(parents=True) Path().iterdir() # 迭代当前目录,是个生成器 for x in Path().iterdir(): if x.is_dir(): print(x)
6、通配符,rglob(*.py)这个是递归获取,和最后一种一样 print(list(Path(‘D:/‘,‘QQLive‘).glob(‘*.gz‘))) print(list(Path(‘D:/‘,‘QQLive‘).glob(‘*/*.gz‘))) # 找本层和上一层 print(list(Path(‘D:/‘,‘QQLive‘).glob(‘**/*.gz‘))) # 找本层和任意层
7、匹配 match from pathlib import Path print(Path(‘a/b.py‘).match(‘.py‘)) print(Path(‘.py‘).match(‘*.py‘)) # .py是隐藏文件,用*是匹配0个 print(Path(‘a/b/c.py‘).match(‘a/*py‘)) print(Path(‘a/b/c.py‘).match(‘a/*/*py‘)) # */,没有或一级 print(Path(‘a/b/c.py‘).match(‘a/**/*py‘))
8、文件操作 from pathlib import Path p = Path(‘D:/QQlive/hello‘) p.mkdir() p = p/‘hello.txt‘ p.touch() print(p.match(‘*txt‘)) # p.open(‘r+‘) # 没有则w+ with p.open(‘r+‘) as f: f.write(‘abc‘) # 直接调用下面的也一样 p.write_text(‘abc‘) p.read_text(2) p.write_bytes(b‘hello‘) p.read_bytes()
2、os模块
import os import sys print(os.name) # print(os.uname()) # linux的命令 print(os.listdir(‘D:/‘)) # 返回目录内容列表 print(sys.platform) # 显示win32,64 print(os.listdir()) print(os.stat(‘D:/‘)) # 获取权限等属性 os.chmod(‘test‘,0o777) os.chown(path,uid,gid) # 改变属主,属组
3、shutil模块
import os import shutil with open(‘o:/test‘,‘r+‘) as f1: f1.write(‘abcde‘) f1.flush() f1.seek(0) with open(‘0:/test1‘,‘w+‘) as f2: shutil.copyfileobj(f1,f2) # 复制内容 shutil.copyfile(‘D:\QQLive/test.txt‘,‘D:\QQLive/test2.txt‘) # 复制内容,本质上还是obj的用法 shutil.copymode(‘D:\QQLive/test.txt‘,‘D:\QQLive/test2.txt‘) # 仅仅复制权限 shutil.copystat(‘test‘,‘test1‘) # 复制元数据,包括权限 shutil.copytree(‘src‘,‘dst‘) # copy2可以拷贝权限属性内容,比copy多属性 # src必须存在,dst必须不存在,递归复制目录,默认使用copy2,不拷贝隐藏文件 shutil.rmtree(‘path‘) # 递归删除,慎用,不是原子操作,删到一半失败了,前面的没了 os.rename(‘D:/QQlive/test2.txt‘,‘D:/dst‘) # 这就是move,从哪里改到哪里
二、csv文件
1、逗号分割的值,也可以自定义分割符 2、被行分隔符,列分隔符划分成行和列的文本文件 3、行分割符为、\r\n,最后一行可以没有换行符 4、列分隔符常为逗号或者制表符 5、每一行成为一条记录record 6、字段可以双引号括起来,也可以不使用,如果字段中出现了双引号,逗号,换行符必须使用双引号括起来,如果字段的值是双引号,使用两个双引号表示一个转义
7、 import os s = """\ # 第一行换行去掉,小技巧 1,tom,20, 2,jerry,16, 3""" with open(‘D:/QQlive/test.csv‘,‘w‘) as f: for line in s.splitlines(): f.write(line +"\n")
8、 import csv from pathlib import Path p = Path(‘D:/QQlive/test.csv‘) if not p.parent.exists(): p.parent.mkdir(parents=True) s = ‘‘‘ 1,tom,20, 2,jerry,16, 3,,, ‘‘‘ line1 = [1,"tom",20,‘‘] line2 = [2,"tom",20,‘‘] line3 = [line1, line2] with open(str(p),‘w‘) as f: writer = csv.writer(f) writer.writerow(line1) writer.writerow(line2) writer.writerows(line3) with open(str(p)) as f: reader = csv.reader(f) for line in reader: if line: print(line)
9、ini文件,配置文件 from configparser import ConfigParser cfg = ConfigParser() cfg.read(‘D:/QQlive/test.ini‘) cfg.sections() # 区 for section in cfg.sections(): for option in cfg.options(section): # key print(section,option) # for k,v in cfg.items(): # print(k,v) for k,v in cfg.items(section): print(k,v) if not cfg.has_section(‘test‘): cfg.add_section(‘test‘) cfg.set(‘test‘,‘test1‘,‘123‘) cfg.set(‘test‘,‘test2‘,‘abc‘) # 内存中操作,没写入文件内,下面写进去 with open("D:/QQlive/test.ini",‘w‘) as f: cfg.write(f) a = cfg.get(‘test‘,‘test1‘) print(a) b = cfg.getint(‘test‘,‘test1‘) print(b) cfg.remove_option(‘test‘,‘test2‘)
三、序列化和反序列化
1、serialization 序列化 将内存中对象存储下来,变成一个个字节--》二进制 2、deserialization 反序列化 将文件中的一个个字节恢复成内存中对象 《--二进制 3、序列化保存到文件就是持久化 可以将数据序列化后持久化,或者网络传输,也可以将文件中或者网络接受到的字节序列反序列化
4、pickle库,只解决python的序列化 dumps 对象序列化 dump 对象序列化到文件对象,就是存入文件 loads 对象反序列化 load 对象反序列化,从文件读取数据 # 反序列化必须有对应的数据类型,否则报错,尤其是自定义类,必须远程得有
import pickle lst = ‘a b c‘.split() d = dict(zip(‘abc‘,range(3))) with open("D:/QQlive/pickle",‘wb‘) as f: pickle.dump(lst,f) # 序列化,生成在上面文件中 pickle.dump(d,f) with open("D:/QQlive/pickle",‘rb‘) as f: tmp = pickle.load(f) # 反序列化,需要接住 print(tmp) tmp = pickle.load(f) print(tmp)
四、json
1、值:双引号引起来的字符串"",数值123,true和false,null,对象{},数组[] 2、字符串,由双引号包起来的任意字符,包括中文 3、数值,正负,整数,浮点数 4、对象:无序的键值对的组合,格式:{key1:value1,..,keyn:valuen},key必须是字符串 5、数组,有序的值的组合:[value1,..,valuen]
6、json类型 Python类型 Json类型 True true False false None null 一个空值 str string int integer float float list array dict object
7、 import json d={‘a‘:123,‘b‘:[‘abc‘,{‘c‘:234}],‘d‘:True,‘e‘:False,‘f‘:None} print(d) class AA: def ser(self): return ‘AA‘ a = json.dumps(d) print(a) print(json.dumps(AA().ser()))
五、MessagePack二进制的序列化
import json import msgpack js = {‘a‘:123,‘b‘:[‘abc‘,{‘c‘:234}],‘d‘:True,‘e‘:False,‘f‘:None} a = json.dumps(js) print(a) b = json.loads(a) print(b) c = msgpack.packb(js) print(c) d = msgpack.unpackb(c,encoding=‘utf-8‘) # encoding转换注意 print(d)
本文出自 “13277682” 博客,谢绝转载!
以上是关于Python第六课----IO和序列化的主要内容,如果未能解决你的问题,请参考以下文章