python文件處理、路徑處理踪宠、序列化和反序列化

文件IO常用操作

一般說IO操作自赔,指的是文件IO,如果指的是網(wǎng)絡(luò)IO柳琢,會直接說绍妨。

把文件存儲到磁盤上的這個(gè)過程,叫做落地柬脸。

column column
open 打開
read 讀取
write 寫入
close 關(guān)閉
readline 行讀取
readlines 多行讀取
seek 文件指針操作
tell 指針位置
open打開操作
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True,opener=None)

f = open("file名字")   #文件對象
print(f.read())     #讀取文件
f.close()       #關(guān)閉文件

打開一個(gè)文件痘绎,返回一個(gè)文件對象(流對象)和文件描述符。打開文件失敗肖粮,則返回異常孤页。
基本使用: 創(chuàng)建一個(gè)文件test,然后打開它涩馆,用完關(guān)閉行施。

文件操作中最常用的就是讀和寫允坚。文件訪問的模式有兩種:文本模式和二進(jìn)制模式。

注:windows中使用codepage代碼頁蛾号〕硐睿可以認(rèn)為每一個(gè)代碼頁就是一張編碼表 cp936和gbk等價(jià)。

mode模式
描述字符
r 缺省的鲜结,表示只讀打開
w 只寫打開展运,有的話就清除重新寫
x 創(chuàng)建并寫入一個(gè)新文件
a 寫入打開,如果文件存在精刷,則追加
b 二進(jìn)制模式
t 缺省的拗胜,文本模式
+ 讀寫打開一個(gè)文件,給原來只讀怒允、只寫的增加缺失的功能

open默認(rèn)是只讀模式r打開已經(jīng)存在的文件埂软。

  • r 只讀打開文件,如果使用write方法纫事,會拋異常勘畔。 如果文件不存在,拋出FileNotFoundError異常丽惶。

  • w 表示只寫方式打開炫七,如果讀取則拋出異常 如果文件不存在,則直接創(chuàng)建文件 如果文件存在钾唬,則清空文件內(nèi)容诉字。

  • x 文件不存在,創(chuàng)建文件知纷,并只寫方式打開,文件存在陵霉,拋出FileExistsError異常琅轧。

  • a 文件存在,只寫打開踊挠,追加內(nèi)容 文件不存在乍桂,則創(chuàng)建后,只寫打開效床,追加內(nèi)容

  • r是只讀睹酌,wxa都是只寫。 wxa都可以產(chǎn)生新文件剩檀,w不管文件存在與否憋沿,都會生成全新內(nèi)容的文件;a不管文件是否存在沪猴,都能在打開的文件尾部追加辐啄;x必須要求文件事先不存在采章,自己造一個(gè)新文件。

  • +為r壶辜、w悯舟、a、x提供缺失的讀或?qū)懝δ茉颐瘢堑衷酰@取文件對象依舊按照r、w岭参、a反惕、x自己的特征。 +不能單獨(dú)使用冗荸,可以認(rèn)為它是為前面的模式字符做增強(qiáng)功能的承璃。

t和b:

  • 文本模式t 字符流,將文件的字節(jié)按照某種字符編碼理解蚌本,按照字符操作盔粹。open的默認(rèn)mode就是rt。

  • 二進(jìn)制模式b 字節(jié)流程癌,將文件就按照字節(jié)理解舷嗡,與字符編碼無關(guān)。二進(jìn)制模式操作時(shí)嵌莉,字節(jié)操作使用bytes類型进萄。

t/b不能單獨(dú)存在,要和a/w/x/r配合使用锐峭。

seek文件指針

文件指針中鼠,指向當(dāng)前字節(jié)位置。

mode = r沿癞,指針起始在0 援雇,mode = a 指針起始在EOF。

tell():顯示指針當(dāng)前位置椎扬。

seek(offset[, whence]) 移動文件指針位置惫搏。offest偏移多少字節(jié),whence從哪里開始蚕涤。

  • 文本模式下 whence 0 缺省值筐赔,表示從頭開始,offest只能正整數(shù) whence 1 表示從當(dāng)前位置揖铜,offest只接受0茴丰,whence 2 表示從EOF開始,offest只接受0

    # 文本模式
    f = open('test4','r+')
    f.tell() # 起始
    f.read()
    f.tell() # EOF
    f.seek(0) # 起始
    f.read()
    f.seek(2,0)
    f.read()
    f.seek(2,0)
    f.seek(2,1) # offset必須為0
    f.seek(2,2) # offset必須為0
    f.close()
    
  • 二進(jìn)制模式下 whence 0 缺省值,表示從頭開始较沪,offest只能正整數(shù) whence 1表示從當(dāng)前位置鳞绕,offest可正可負(fù),whence 2 表示從EOF開始尸曼,offest可正可負(fù)们何。

    # 二進(jìn)制模式
    f = open('test4','rb+')
    f.tell() # 起始
    f.read()
    f.tell() # EOF
    f.write(b'abc')
    f.seek(0) # 起始
    f.seek(2,1) # 從當(dāng)前指針開始,向后2
    f.read()
     
    f.seek(-2,2) # 從EOF開始控轿,向前2
    f.read()
    f.seek(-20,2) # OSError
    f.close()
    
  • 二進(jìn)制模式支持任意起點(diǎn)的偏移冤竹,從頭、從尾茬射、從中間位置開始鹦蠕。 向后seek可以超界,但是向前seek的時(shí)候在抛,不能超界钟病,否則拋異常。

buffering緩沖區(qū)

-1 表示使用缺省大小的buffer刚梭。如果是二進(jìn)制模式肠阱,使io.DEFAULT_BUFFER_SIZE值,默認(rèn)是<font color= red>4096或者8192</font>朴读。如果是文本模式屹徘,如果是終端設(shè)備,是行緩存方式衅金,如果不是噪伊,則使用二進(jìn)制模式的策略。

  • 0 只在二進(jìn)制模式使用氮唯,表示關(guān)buffer
  • 1 只在文本模式使用鉴吹,表示使用行緩沖。意思就是見到換行符就flush
  • 大于1 用于指定buffer的大小

buffer 緩沖區(qū)

緩沖區(qū)一個(gè)內(nèi)存空間惩琉,一般來說是一個(gè)FIFO隊(duì)列豆励,到緩沖區(qū)滿了或者達(dá)到閾值,數(shù)據(jù)才會flush到磁盤琳水。

flush() 將緩沖區(qū)數(shù)據(jù)寫入磁盤 close() 關(guān)閉前會調(diào)用flush()。

io.DEFAULT_BUFFER_SIZE 缺省緩沖區(qū)大小般堆,字節(jié)在孝。

buffering 說明
buffering = -1 t和b,都是io.DEFAULT_BUFFER_SIZE
buffering = 0 b 關(guān)閉緩沖區(qū)
t 不支持
buffering = 1 b 就一個(gè)字節(jié)
t 行緩沖淮摔,遇到換行符才flush
buffering > 1 b模式表示行緩沖大小私沮。緩沖區(qū)的值可以超過io.DEFAULT_BUFFER_SIZE,直到設(shè)定的值超出后才把緩沖區(qū)flush 和橙。
t模式仔燕,是io.DEFAULT_BUFFER_SIZE字節(jié)造垛,flush完后把當(dāng)前字符串也寫入磁盤

一般來說:

  1. 文本模式,一般都用默認(rèn)緩沖區(qū)大小
  2. 二進(jìn)制模式晰搀,是一個(gè)個(gè)字節(jié)的操作五辽,可以指定buffer的大小
  3. 一般來說,默認(rèn)緩沖區(qū)大小是個(gè)比較好的選擇外恕,除非明確知道杆逗,否則不調(diào)整它
  4. 一般編程中,明確知道需要寫磁盤了鳞疲,都會手動調(diào)用一次flush罪郊,而不是等到自動flush或者close的時(shí)候
其他參數(shù)

編碼:windows下缺省GBK(0xB0A1),Linux下缺省UTF-8(0xE5 95 8A)

errors :編碼錯(cuò)誤將被捕獲 None和strict表示有編碼錯(cuò)誤將拋出ValueError異常尚洽;ignore表示忽略

newline:文本模式中悔橄,換行的轉(zhuǎn)換∠俸粒可以為None癣疟、'' 空串、'\r'拴曲、'\n'争舞、'\r\n' 。

  • None表示'\r'澈灼、'\n'竞川、'\r\n'都被轉(zhuǎn)換為'\n';
  • '' 表示不會自動轉(zhuǎn)換通用換行符叁熔;其它合法字符表示換行符就是指定字符委乌,就會按照指定字符分行寫。
  • '\n'或''表示'\n'不替換荣回;其它合法字符表示'\n'會被替換為指定的字符

closefd:關(guān)閉文件描述符遭贸,True表示關(guān)閉它。False會在文件關(guān)閉后保持這個(gè)描述符心软。fileobj.fileno()查看壕吹。

文件描述符:Linux一切皆文件,文件打開后都會有一個(gè)位于的文件描述符删铃,在計(jì)算機(jī)系統(tǒng)中是一個(gè)有限的資源耳贬。0,1,2,標(biāo)準(zhǔn)輸入,標(biāo)準(zhǔn)輸出猎唁,標(biāo)準(zhǔn)錯(cuò)誤輸出咒劲。

對于類似于文件對象的IO對象,一般來說都需要在不使用的時(shí)候關(guān)閉、注銷腐魂,以釋放資源帐偎。
IO被打開的時(shí)候,會獲得一個(gè)文件描述符蛔屹。計(jì)算機(jī)資源是有限的削樊,所以操作系統(tǒng)都會做限制。就是為了保護(hù)計(jì)算機(jī)的資源不要被完全耗盡判导,計(jì)算資源是共享的嫉父,不是獨(dú)占的。

一般情況下眼刃,除非特別明確的知道資源情況绕辖,否則不要提高資源的限制值來解決問題。

read()

read(size=-1)
size表示讀取的多少個(gè)字符或字節(jié)擂红;負(fù)數(shù)或者None表示讀取到EOF

readline(size=-1)
一行行讀取文件內(nèi)容仪际。size設(shè)置一次能讀取行內(nèi)幾個(gè)字符或字節(jié)。

readlines(hint=-1)
讀取所有行的列表昵骤。指定hint則返回指定的行數(shù)树碱。

write()

write(s),把字符串s寫入到文件中并返回字符的個(gè)數(shù) writelines(lines)变秦,將字符串列表寫入文件成榜。

close()

flush并關(guān)閉文件對象。
文件已經(jīng)關(guān)閉蹦玫,再次關(guān)閉沒有任何效果赎婚。

其他
名稱 說明
seekable() 是否可seek
readable() 是否可讀
writeable() 是否可寫
closed() 是否已經(jīng)關(guān)閉
上下文管理

1、異常處理
當(dāng)出現(xiàn)異常的時(shí)候樱溉,攔截異常挣输。但是,因?yàn)楹芏啻a都可能出現(xiàn)OSError異常福贞,還不好判斷異常就是應(yīng)為資源限制產(chǎn)生的撩嚼。

f = open('test')
try:
    f.write("abc") # 文件只讀,寫入失敗
finally:
    f.close() # 這樣才行

使用finally可以保證打開的文件可以被關(guān)閉挖帘。

上下文管理

  1. 使用with ... as 關(guān)鍵字

  2. 上下文管理的語句塊并不會開啟新的作用域

  3. with語句塊執(zhí)行完的時(shí)候完丽,會自動關(guān)閉文件對象

StringIO操作

io模塊中的類

from io import StringIO

內(nèi)存中,開辟的一個(gè)文本模式的buffer拇舀,可以像文件對象一樣操作它

當(dāng)close方法被調(diào)用的時(shí)候逻族,這個(gè)buffer會被釋放

from io import StringIO
# 內(nèi)存中構(gòu)建
sio = StringIO() # 像文件對象一樣操作
print(sio.readable(), sio.writable(), sio.seekable())# True True True
sio.write("magedu\nPython")
sio.seek(0)  
print(sio.readline())  #magedu
print(sio.getvalue()) # 無視指針,輸出全部內(nèi)容  magedu   Python
sio.close()

好處

一般來說你稚,磁盤的操作比內(nèi)存的操作要慢得多瓷耙,內(nèi)存足夠的情況下,一般的思路是少落地刁赖,減少磁盤IO的過程搁痛,可以大大的提高程序的運(yùn)行效率。

BytesIO操作

io模塊中的類

from io import BytesIO

內(nèi)存中宇弛,開辟的一個(gè)二進(jìn)制模式的buffer鸡典,可以像文件對象一樣操作它

當(dāng)close方法被調(diào)用的時(shí)候,這個(gè)buffer會被釋放

from io import BytesIO # 內(nèi)存中構(gòu)建
bio = BytesIO()
print(bio.readable(), bio.writable(), bio.seekable()) #True True True
bio.write(b"magedu\nPython")
bio.seek(0)
print(bio.readline())  # b'magedu\n'
print(bio.getvalue()) # 無視指針枪芒,輸出全部內(nèi)容   b'magedu\nPython'
bio.close()

file-like對象

類文件對象彻况,可以像文件對象一樣操作。

socket對象舅踪,輸入輸出對象(stdin纽甘、stdout)都是類文件對象

from sys import stdout, stderr
f = stdout
print(type(f))  #<class 'ipykernel.iostream.OutStream'>
f.write('magedu.com')  #magedu.com

路徑操作

os.path模塊

3.4版本之前

from os import path
p = path.join('d:/','tmp')
print(type(p), p)               #<class 'str'> d:/tmp
print(path.exists(p))     #判斷是否存在該路徑  True
print(path.split(p)) # (head,tail)     ('d:/', 'tmp')
print(path.abspath('.'))   # 打印當(dāng)前的絕對路徑      C:\Users\vampire\python
p = path.join('D:/', p, 'test.txt')   #  'd:/tmp\\test.txt'
print(path.dirname(p)) # 目錄名
print(path.basename(p)) #基名,就是文件名
print(path.splitdrive(p)) #二元組  ('d:', '/tmp\\test.txt')

p1 = path.abspath(".")  #“文件路徑”
print(p1, path.basename(p1))
while p1 != path.dirname(p1):
    p1 = path.dirname(p1)
    print(p1, path.basename(p1))

?```
C:\Users\vampire\python python
C:\Users\vampire vampire
C:\Users Users
C:\ 
?```
pathlib模塊

提供Path對象來操作抽碌。包括目錄和文件悍赢。

導(dǎo)入模塊:from pathlib import Path

目錄操作初始化

p = Path() # 當(dāng)前目錄    WindowsPath('.')
p.absolute()#   WindowsPath('C:/Users/vampire/python')
p = Path('a','b','c/d') # 當(dāng)前目錄下的 WindowsPath('C:/Users/vampire/python/a/b/c/d')
p = Path('/etc') # 根下的etc目錄

路徑拼接和分解

操作符/

Path對象 / Path對象
Path對象 / 字符串 或者 字符串 / Path對象

分解

parts屬性,可以返回路徑中的每一個(gè)部分

p3.absolute()   #WindowsPath('C:/Users/vampire/python/c/a')
p3.absolute().parts   #('C:\\', 'Users', 'vampire', 'python', 'c', 'a')
joinpath

joinpath(*other) 連接多個(gè)字符串到Path對象中

p = Path()   #   WindowsPath('.')
p = p / 'a'   #  WindowsPath('a')
p.absolute()  #   WindowsPath('C:/Users/vampire/python/a')
p1 = 'b' / p  #   WindowsPath('C:/Users/vampire/python/b/a')
p2 = Path('c') #  WindowsPath('C:/Users/vampire/python/c')
p2.absolute()  #   WindowsPath('C:/Users/vampire/python/c')
p3 = p2 / p1  #  WindowsPath('c/b/a')
p3.absolute()  #  WindowsPath('C:/Users/vampire/python/c/b/a')
print(p3.parts)   #
p3.absolute().parts # ('C:\\', 'Users', 'vampire', 'python', 'c', 'b', 'a')
p3.joinpath('etc','init.d',Path('httpd'))
獲取路徑

str 獲取路徑字符串

bytes 獲取路徑字符串的bytes

p = Path('/etc')
print(str(p), bytes(p))

#  \etc   b'\\etc'
父目錄

parent 目錄的邏輯父目錄

parents 父目錄序列货徙,索引0是直接的父

p = Path('/a/b/c/d')
print(p.absolute())   #C:\a\b\c\d
print(p.parent.parent)  #\a\b
for x in p.parents:
    print(x)
    
#\a\b\c
#\a\b
#\a
#\
目錄的組合部分

name左权、stem、suffix痴颊、suffixes赏迟、with_suffix(suffix)、with_name(name)

name 目錄的最后一個(gè)部分

suffix 目錄中最后一個(gè)部分的擴(kuò)展名

stem 目錄最后一個(gè)部分蠢棱,沒有后綴

suffixes 返回多個(gè)擴(kuò)展名列表

with_suffix(suffix) 有擴(kuò)展名則替換锌杀,無則補(bǔ)充擴(kuò)展名

with_name(name) 替換目錄最后一個(gè)部分并返回一個(gè)新的路徑

p = Path('mysqlinstall/mysql.tar.gz')
print(p.name)   #mysql.tar.gz
print(p.suffix)  #.gz
print(p.suffixes)  # ['.tar', '.gz']
print(p.stem)   # mysql.tar
print(p.with_name('mysql-5.tgz'))   #\mysqlinstall\mysql-5.tgz
print(p.with_suffix('.png'))   #\mysqlinstall\mysql.tar.png
p = Path('README')  #  README
print(p.with_suffix('.txt'))   #  README.txt
判斷方法

is_dir() 是否是目錄,目錄存在返回True

is_file() 是否是普通文件裳扯,文件存在返回True

is_symlink() 是否是軟鏈接

is_socket()是否是socket文件

is_block_device()是否是塊設(shè)備

is_char_device() 是否是字符設(shè)備

is_absolute()是否是絕對路徑

resolve()返回一個(gè)新的路徑抛丽,這個(gè)新路徑就是當(dāng)前Path對象的絕對路徑,如果是軟鏈接則直接被解析

absolute() 獲取絕對路徑

exists()目錄或文件是否存在

rmdir()刪除空目錄饰豺。沒有提供判斷目錄為空的方法

touch(mode=0o666, exist_ok=True) 創(chuàng)建一個(gè)文件

as_uri() 將路徑返回成URI亿鲜,例如'file:///etc/passwd'

mkdir(mode=0o777, parents=False, exist_ok=False)

  • parents,是否創(chuàng)建父目錄冤吨,True等同于mkdir -p蒿柳;False時(shí),父目錄不存在漩蟆,則拋出FileNotFoundError

  • exist_ok參數(shù)垒探,在3.5版本加入。False時(shí)怠李,路徑存在圾叼,拋出FileExistsError蛤克;True時(shí),F(xiàn)ileExistsError被忽略

iterdir()迭代當(dāng)前目錄

匹配

match(pattern)

模式匹配夷蚊,成功返回True构挤。

Path('a/b.py').match('*.py') # True
Path('/a/b/c.py').match('b/*.py') # True
Path('/a/b/c.py').match('a/*.py') # False
Path('/a/b/c.py').match('a/*/*.py') # True
Path('/a/b/c.py').match('a/**/*.py') # True
Path('/a/b/c.py').match('**/*.py') # True

stat() 相當(dāng)于stat命令 ,lstat() 同stat()惕鼓,但如果是符號鏈接筋现,則顯示符號鏈接本身的文件信息

pathlib模塊下的文件操作

Path.open(mode='r', buffering=-1, encoding=None, errors=None, newline=None)

使用的方法類似內(nèi)建函數(shù)open,返回一個(gè)文件對象箱歧。

3.5增加的新函數(shù)

Path.read_bytes()

以'rb'讀取路徑對應(yīng)文件矾飞,并返回二進(jìn)制流⊙叫希看源碼

Path.read_text(encoding=None, errors=None)

以'rt'方式讀取路徑對應(yīng)文件洒沦,返回文本。

Path.write_bytes(data)

以'wb'方式寫入數(shù)據(jù)到路徑對應(yīng)文件价淌。

Path.write_text(data, encoding=None, errors=None)

以'wt'方式寫入字符串到路徑對應(yīng)文件微谓。

p = Path('my_binary_file')
p.write_bytes(b'Binary file contents')
p.read_bytes() # b'Binary file contents'
 
p = Path('my_text_file')
p.write_text('Text file contents')
p.read_text() # 'Text file contents'
 
 
from pathlib import Path
p = Path('o:/test.py')
p.write_text('hello python')
print(p.read_text())
with p.open() as f:
    print(f.read(5))

csv文件

逗號分隔值Comma-Separated Values。

CSV 是一個(gè)被行分隔符输钩、列分隔符劃分成行和列的文本文件豺型。

CSV 不指定字符編碼。

行分隔符為\r\n买乃,最后一行可以沒有換行符

列分隔符常為逗號或者制表符姻氨。

每一行稱為一條記錄record

字段可以使用雙引號括起來,也可以不使用剪验。如果字段中出現(xiàn)了雙引號肴焊、逗號、換行符必須使用雙引號括起來功戚。如果字段的值是雙引號娶眷,使用兩個(gè)雙引號表示一個(gè)轉(zhuǎn)義。

表頭可選啸臀,和字段列對齊就行了届宠。

手動生成csv文件

from pathlib import Path

p = Path('D:/tmp/test.csv')
parent = p.parent
if not parent.exists():
    parent.mkdir(parents=True,exist_ok =True) #exist_ok 用在python3.5之后,如果文件目錄存在乘粒,True則壓制異常豌注。
csv_body = '''\
id,name,age,comment
1,zs,18,"I'm 18"
2,ls,20,"this is a ""test"" string."
3,ww,23,"你好

計(jì)算機(jī)
"
'''
p.write_text(csv_body)

csv模塊
def reader(iterable, dialect='excel', *args, **kwargs)

返回一個(gè)reader對象,是一個(gè)行迭代器

默認(rèn)使用excel方言灯萍,如下:

  • delimiter 列分隔符,逗號

  • lineterminator 行分隔符\r\n

  • quotechar 字段的引用符號轧铁,缺省為"雙引號

  • 雙引號的處理

    • doublequote 雙引號的處理,默認(rèn)為True旦棉。如果碰到數(shù)據(jù)中有雙引號齿风,而quotechar也是雙引號药薯,True則使用2個(gè)雙引號表示,F(xiàn)alse表示使用轉(zhuǎn)義字符將作為雙引號的前綴救斑。
    • escapechar 一個(gè)轉(zhuǎn)義字符果善,默認(rèn)為None
    • writer = csv.writer(f, doublequote=False, escapechar='@') 遇到雙引號,則必須提供轉(zhuǎn)義字符
  • quoting 指定雙引號的規(guī)則

    • QUOTE_ALL 所有字段

    • QUOTE_MINIMAL特殊字符字段系谐,Excel方言使用該規(guī)則

    • QUOTE_NONNUMERIC非數(shù)字字段

    • QUOTE_NONE都不使用引號。

def writer(fileobj, dialect='excel', *args, **kwargs)

返回DictWriter實(shí)例讨跟,主要的方法有writerow纪他,writerows。

import csv
 
p = Path('d://tmp/tesr.csv')
with open(str(p)) as f:
    reader = csv.reader(f)    #返回一個(gè)迭代對象
    print(next(reader))     #不回頭
    print(next(reader))     
    for line in reader:
        print(line)
 
rows = [
    [4,'tom',22,'tom'],
    (5,'jerry',24,'jerry'),
    (6,'justin',22,'just\t"in'),
    "abcdefghi",
    ((1,),(2,))
]
row = rows[0]
 
with open(str(p), 'a',newline="") as f:  #newline為了不換行
    writer = csv.writer(f)
    writer.writerow(row)   #一次寫一條
    writer.writerows(rows)    #將所有的一次寫入

ini文件

一般作為配置文件晾匠。

ini文件:

[DEFAULT]
a = test
 
[mysql]
default-character-set=utf8
 
[mysqld]
datadir =/dbserver/data
port = 33060
character-set-server=utf8
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

中括號里面的部分稱為section茶袒,譯作節(jié)、區(qū)凉馆、段薪寓。

每一個(gè)section內(nèi),都是key=value形成的鍵值對澜共,key稱為option選項(xiàng)向叉。

這里的DEFAULT是缺省section的名字,必須大寫嗦董。

configparser模塊

configparser模塊的ConfigParser類就是用來操作母谎。

可以將section當(dāng)做key,section存儲著鍵值對組成的字典京革,可以把ini配置文件當(dāng)做一個(gè)嵌套的字典奇唤。默認(rèn)使用的是有序字典。

read(filenames, encoding=None) 
#讀取ini文件匹摇,可以是單個(gè)文件咬扇,也可以是文件列表±炔可以指定文件編碼懈贺。
sections()  #返回section列表。缺省section不包括在內(nèi)坡垫。 
add_section(section_name)   #增加一個(gè)section隅居。 

has_section(section_name)   #判斷section是否存在 
options(section)   #返回section的所有option,會追加缺省section的option 

has_option(section, option)  #判斷section是否存在這個(gè)option
get(section, option, *, raw=False, vars=None[, fallback]) 

#從指定的段的選項(xiàng)上取值葛虐,如果找到返回胎源,如果沒有找到就去找DEFAULT段有沒有。

getint(section, option, *, raw=False, vars=None[, fallback]) 
getfloat(section, option, *, raw=False, vars=None[, fallback]) 
getboolean(section, option, *, raw=False, vars=None[, fallback]) 
#上面3個(gè)方法和get一樣屿脐,返回指定類型數(shù)據(jù)涕蚤。

items(raw=False, vars=None) 
items(section, raw=False, vars=None) 
#沒有section宪卿,則返回所有section名字及其對象;如果指定section万栅,則返回這個(gè)指定的section的鍵值對組成二元組佑钾。

set(section, option, value) 
#section存在的情況下,寫入option=value烦粒,要求option休溶、value必須是字符串。

remove_section(section) 
#移除section及其所有option 

remove_option(section, option) 
#移除section下的option扰她。

write(fileobject, space_around_delimiters=True) 
#將當(dāng)前config的所有內(nèi)容寫入fileobject中兽掰,一般open函數(shù)使用w模式。

代碼示例:

from configparser import ConfigParser
from pathlib import Path

filename = Path("d://tmp/mysql.ini")
newfilename = Path("d://tmp/mysql111.ini")

cfg = ConfigParser()
read_ok = cfg.read(str(filename))
print(read_ok)
print(cfg.sections())
print(cfg.has_section("mysql"))
print("-"*30)

for k,v in cfg.items():   #未指定section
    print(k,type(k))
    print(v,type(v))
    print(cfg.items(k))
    print("~~~~~~~~~~~~~~~~~~")
print("-"*30)


for k,v in cfg.items("mysqld"):  #指定section
    print(k,type(k))
    print(v,type(v))
    print("~~~~~~~~~~")

tmp = cfg.get("mysqld","port")
print(tmp, type(tmp))
print(cfg.get("mysqld", "a"))
print(cfg.get("mysqld", "python" , fallback= "linux"))  #按照類型徒役,fallbac:給與缺省值

tmp = cfg.getint("mysqld", "port")
print(type(tmp), tmp)

cfg.add_section("test")
cfg.set("test","test1","1")
cfg.set("test","test2","2")
with open(newfilename,"w+",newline="") as f:
    cfg.write(f)

print(cfg.getint("test" , "test1"))

cfg.remove_option("test", "test1")
# cfg.remove_section("test")
# print("x" in cfg["test2"])
#字典操作
cfg["test3"] = {"c":"1000"}   #沒有落地孽尽,在內(nèi)存中修改

print("x" in cfg["test"])
print("c" in cfg["test3"])

# 其他內(nèi)部方式
print(cfg._dict)  # 返回默認(rèn)的字典類型,默認(rèn)使用有序字典

for k, v in cfg._sections.items():
    print(k, v)

for k,v in cfg._sections['mysqld'].items():
    print(k,v)
#重新寫入文件
with open(newfilename, 'w') as f:
    cfg.write(f)

序列化和反序列化

要設(shè)計(jì)一套協(xié)議忧勿,按照某種規(guī)則杉女,把內(nèi)存中數(shù)據(jù)保存到文件中,文件是一個(gè)字節(jié)序列鸳吸,所以必須把數(shù)據(jù)轉(zhuǎn)換成<font color=red >字節(jié)</font>序列熏挎,輸出到文件。這就是序列化晌砾。反之婆瓜,從文件的字節(jié)序列恢復(fù)到內(nèi)存。就是反序列化贡羔。
  1. serialization:序列化
    將內(nèi)存中對象存儲下來廉白,變成一個(gè)個(gè)字節(jié) --> 二進(jìn)制

  2. deseiralization:反序列化
    將文件中的一個(gè)個(gè)字節(jié)恢復(fù)成內(nèi)存中對象 <--二進(jìn)制

序列化保存到文件就是持久化,可以將數(shù)據(jù)序列化后持久化乖寒,或者網(wǎng)絡(luò)傳輸猴蹂;也可以將文件中或者網(wǎng)絡(luò)中接收到的字節(jié)序列反序列化。

pickle庫

python中的序列化楣嘁,反序列化模塊磅轻。

dumps 對象序列化為bytes對象 dump 對象序列化到文件對象,就是存入文件

loads 從bytes對象反序列化 load 對象反序列化逐虚,從文件讀取數(shù)據(jù)

序列化的應(yīng)用

一般來說聋溜,本地序列化的情況,應(yīng)用較少叭爱。大多數(shù)場景都應(yīng)用在網(wǎng)絡(luò)傳輸中撮躁。

將數(shù)據(jù)序列化后通過網(wǎng)絡(luò)傳輸?shù)竭h(yuǎn)程節(jié)點(diǎn),遠(yuǎn)程服務(wù)器上的服務(wù)將接收到的數(shù)據(jù)反序列化后买雾,就可以使用了把曼。

但是杨帽,要注意一點(diǎn),遠(yuǎn)程接收端嗤军,反序列化時(shí)必須有對應(yīng)的數(shù)據(jù)類型注盈,否則就會報(bào)錯(cuò)。尤其是自定義類叙赚,必須遠(yuǎn)程的有一致的定義老客。

現(xiàn)在,大多數(shù)項(xiàng)目震叮,都不是單機(jī)的胧砰,也不是單服務(wù)的。需要通過網(wǎng)絡(luò)將數(shù)據(jù)傳送到其他節(jié)點(diǎn)上去冤荆,這就需要大量的序列化、反序列化過程权纤。

但是钓简,問題是,Python程序之間還可以都是用pickle解決序列化汹想、反序列化外邓,如果是跨平臺、跨語言古掏、跨協(xié)議pickle就不太適合了损话,就需要公共的協(xié)議。例如XML槽唾、Json丧枪、Protocol Buffer等。

不同的協(xié)議庞萍,效率不同拧烦、學(xué)習(xí)曲線不同,適用不同場景钝计,要根據(jù)不同的情況分析選型恋博。

Json
Json(JavaScript Object Notation,JS對象標(biāo)記)是一種輕量級的數(shù)據(jù)交換格式私恬。它基于 ECMAScript (w3c組織制定的JS規(guī)范)的一個(gè)子集债沮,采用完全獨(dú)立于編程語言的文本格式來存儲和表示數(shù)據(jù)。網(wǎng)址: http://json.org/

Json的數(shù)據(jù)類型

值:雙引號引起來的字符串本鸣,數(shù)值疫衩,true和false,null荣德,對象隧土,數(shù)組提针,這些都是值

字符串:有正負(fù),有整數(shù)曹傀,浮點(diǎn)數(shù)辐脖。

對象:無序的鍵值對的集合,格式{key:value...}皆愉,key必須是一個(gè)字符串嗜价,需要雙引號包圍這個(gè)字符串,value可以是任意合法的值幕庐。

數(shù)組:有序的值的集合 格式[val1久锥,,异剥,瑟由,valn]

{
  "person": [
    {
      "name": "tom",
      "age": 18
    },
    {
      "name": "jerry",
      "age": 16
    }
  ],
  "total": 2
}

Json模塊

Python支持少量內(nèi)建數(shù)據(jù)類型到Json類型的轉(zhuǎn)換

Python類型 Json類型
True true
False false
None null
str string
int integer
float float
list array
dict object

常用方法

Python類型 Json類型
dumps Json編碼
dump Json編碼并存入文件
loads Json解碼
load Json解碼,從文件讀取數(shù)據(jù)

一般Json編碼的數(shù)據(jù)很少落地冤寿,數(shù)據(jù)都是通過網(wǎng)絡(luò)傳輸歹苦,傳輸?shù)臅r(shí)候,要考慮壓縮它督怜,節(jié)省流量殴瘦。本質(zhì)來說它就是個(gè)文本,就是個(gè)字符串号杠。

MessagePack

MessagePack是一個(gè)基于二進(jìn)制高效的對象序列化類庫蚪腋,可用于跨語言通信。

它可以像JSON那樣姨蟋,在許多種語言之間交換結(jié)構(gòu)對象屉凯。

兼容 json和pickle。

MessagePack簡單易用眼溶,高效壓縮神得,支持語言豐富。

所以偷仿,用它序列化也是一種很好的選擇哩簿。

安裝:$pip install msgpack-python

常用方法:

packb 序列化對象。提供了dumps來兼容pickle和json酝静。

unpackb 反序列化對象节榜。提供了loads來兼容。

pack 序列化對象保存到文件對象别智。提供了dump來兼容宗苍。

unpack 反序列化對象保存到文件對象。提供了load來兼容。

import pickle
import json
import msgpack

d = {"person":[{"name":"tom","age":18},{"name":"jerry","age":16}],"total":2}
j = json.dumps(d)
print(j, type(j), len(j)) # 請注意引號的變化
print(len(j.replace(' ',''))) # 72 bytes 注意這樣替換的壓縮是不對的
print("-"*30)
p = pickle.dumps(d)
print(p)
print(len(p))  # 101 bytes
print("-"*30)
m = msgpack.dumps(d)
print(m)
print(len(m)) # 48 bytes
print("-"*30)
u = msgpack.unpackb(m)
print(type(u), u)
u = msgpack.loads(m, encoding='utf-8')
print(type(u), u)
{"person": [{"name": "tom", "age": 18}, {"name": "jerry", "age": 16}], "total": 2} <class 'str'> 82
72
------------------------------
b'\x80\x03}q\x00(X\x06\x00\x00\x00personq\x01]q\x02(}q\x03(X\x04\x00\x00\x00nameq\x04X\x03\x00\x00\x00tomq\x05X\x03\x00\x00\x00ageq\x06K\x12u}q\x07(h\x04X\x05\x00\x00\x00jerryq\x08h\x06K\x10ueX\x05\x00\x00\x00totalq\tK\x02u.'
101
------------------------------
b'\x82\xa6person\x92\x82\xa4name\xa3tom\xa3age\x12\x82\xa4name\xa5jerry\xa3age\x10\xa5total\x02'
48
------------------------------
<class 'dict'> {b'person': [{b'name': b'tom', b'age': 18}, {b'name': b'jerry', b'age': 16}], b'total': 2}
<class 'dict'> {'person': [{'name': 'tom', 'age': 18}, {'name': 'jerry', 'age': 16}], 'total': 2}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末讳窟,一起剝皮案震驚了整個(gè)濱河市让歼,隨后出現(xiàn)的幾起案子彻磁,更是在濱河造成了極大的恐慌辰晕,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件育八,死亡現(xiàn)場離奇詭異补箍,居然都是意外死亡改执,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進(jìn)店門坑雅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來辈挂,“玉大人,你說我怎么就攤上這事裹粤≈盏伲” “怎么了?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵遥诉,是天一觀的道長拇泣。 經(jīng)常有香客問我,道長突那,這世上最難降的妖魔是什么挫酿? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任构眯,我火速辦了婚禮愕难,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘惫霸。我一直安慰自己猫缭,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布壹店。 她就那樣靜靜地躺著猜丹,像睡著了一般。 火紅的嫁衣襯著肌膚如雪硅卢。 梳的紋絲不亂的頭發(fā)上射窒,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天,我揣著相機(jī)與錄音将塑,去河邊找鬼脉顿。 笑死,一個(gè)胖子當(dāng)著我的面吹牛点寥,可吹牛的內(nèi)容都是我干的艾疟。 我是一名探鬼主播,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蔽莱!你這毒婦竟也來了弟疆?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤盗冷,失蹤者是張志新(化名)和其女友劉穎怠苔,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體正塌,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡嘀略,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了乓诽。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片帜羊。...
    茶點(diǎn)故事閱讀 37,997評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖鸠天,靈堂內(nèi)的尸體忽然破棺而出讼育,到底是詐尸還是另有隱情,我是刑警寧澤稠集,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布奶段,位于F島的核電站,受9級特大地震影響剥纷,放射性物質(zhì)發(fā)生泄漏痹籍。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一晦鞋、第九天 我趴在偏房一處隱蔽的房頂上張望蹲缠。 院中可真熱鬧,春花似錦悠垛、人聲如沸线定。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽斤讥。三九已至,卻和暖如春湾趾,著一層夾襖步出監(jiān)牢的瞬間芭商,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工搀缠, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留铛楣,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓胡嘿,卻偏偏與公主長得像蛉艾,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 官網(wǎng) 中文版本 好的網(wǎng)站 Content-type: text/htmlBASH Section: User ...
    不排版閱讀 4,367評論 0 5
  • Lua 5.1 參考手冊 by Roberto Ierusalimschy, Luiz Henrique de F...
    蘇黎九歌閱讀 13,738評論 0 38
  • 一勿侯、快捷鍵 ctr+b 執(zhí)行ctr+/ 單行注釋ctr+c ...
    o_8319閱讀 5,782評論 2 16
  • 忽然想起來好多年都沒有看過日落了拓瞪,更不提認(rèn)真的欣賞過它了,就像好久沒有提及過自己的夢想了一樣助琐。 年少難免輕狂祭埂,笑談...
    九月彷徨閱讀 487評論 0 1
  • “你知道圖文里有個(gè)無底坑嗎?”惠子忽然開口說話兵钮。 “這樣啊蛆橡。” “等一下等一下掘譬,你說圖文里有一個(gè)無底坑泰演!你說的是無...
    薩勒姆的女巫閱讀 870評論 0 0