文件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)前字符串也寫入磁盤 |
一般來說:
- 文本模式,一般都用默認(rèn)緩沖區(qū)大小
- 二進(jìn)制模式晰搀,是一個(gè)個(gè)字節(jié)的操作五辽,可以指定buffer的大小
- 一般來說,默認(rèn)緩沖區(qū)大小是個(gè)比較好的選擇外恕,除非明確知道杆逗,否則不調(diào)整它
- 一般編程中,明確知道需要寫磁盤了鳞疲,都會手動調(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)閉挖帘。
上下文管理
使用with ... as 關(guān)鍵字
上下文管理的語句塊并不會開啟新的作用域
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)存。就是反序列化贡羔。
serialization:序列化
將內(nèi)存中對象存儲下來廉白,變成一個(gè)個(gè)字節(jié) --> 二進(jìn)制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}