1. 程式人生 > >Python第六課----IO和序列化

Python第六課----IO和序列化

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和序列化