Python第六課----IO和序列化
阿新 • • 發佈:2017-10-30
python
一、文件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和序列化