01-上章題目講解:在上一章節(jié)里
02-open方法和模式
文件操作:非常重要
馮諾依曼體系架構(gòu)
內(nèi)存:掉電易失
CPU由運(yùn)算器和控制器組成:
- 運(yùn)算器搜吧,完成各種算數(shù)運(yùn)算蚕愤,邏輯運(yùn)算尤溜,數(shù)據(jù)傳輸?shù)葦?shù)據(jù)加工處理
- 控制器,控制程序執(zhí)行
- 存儲(chǔ)器浩聋,用于記憶程序和數(shù)據(jù)祟昭,例如內(nèi)存
- 輸入設(shè)備,將數(shù)據(jù)或者程序輸入到計(jì)算機(jī)中蒂誉,例如鍵盤教藻,鼠標(biāo)
- 輸出設(shè)備,將數(shù)據(jù)或程序的處理結(jié)果展示給用戶拗盒,例如顯示器怖竭,打印機(jī)等
一般說(shuō)IO操作,指的是文件IO,如果指的是網(wǎng)絡(luò)IO陡蝇,都會(huì)直接說(shuō)網(wǎng)絡(luò)IO
機(jī)械磁盤上存的都是二進(jìn)制痊臭,且存儲(chǔ)的數(shù)據(jù)未必是連續(xù)的,所以叫機(jī)械硬盤也叫隨機(jī)訪問(wèn)設(shè)備登夫。
文件IO常用操作
打開(kāi)操作
文件系統(tǒng)是靠目錄管理广匙,文件一定是放在目錄下的;windows和linux文件系統(tǒng)不一樣恼策;windows系統(tǒng)是帶邏輯驅(qū)動(dòng)器鸦致,邏輯驅(qū)動(dòng)器有自己的根潮剪,因?yàn)橛羞壿嬺?qū)動(dòng)器,所以要加盤符分唾;linux是根文件系統(tǒng)抗碰。
f = open(file, mode='r', buffering=None, encoding=None, errors=None, newline=None, closefd=True,opener=None)
打開(kāi)一個(gè)文件,返回一個(gè)文件操作對(duì)象(流對(duì)象)和文件描述符绽乔。打開(kāi)文件失敗弧蝇,則返回異常。打開(kāi)后一定要關(guān)閉折砸。
基本使用:
創(chuàng)建一個(gè)文件test看疗,然后打開(kāi)它,用完關(guān)閉
其中的encoding='cp936',cp936的cp代表codepage睦授,等于gbk編碼两芳;windows默認(rèn)編碼是gbk,linux這是UTF-8;gbk編碼中文是2字節(jié)去枷;UTF-8 編碼常見(jiàn)中文是3個(gè)字節(jié)怖辆;GBK兼容GB2312編碼,但比GB2312包含了更多的漢字:中文存儲(chǔ)時(shí)沉填,第一個(gè)字節(jié)碼值在127256之間疗隶,第二個(gè)字節(jié)碼值在0256之間。
Ipython環(huán)境下運(yùn)行shell命令(前提是linux系統(tǒng)裝的有ipython翼闹,這樣在ipython環(huán)境下運(yùn)行shell命令時(shí)才可以)斑鼻,需要在命令前加 ! ,例如 !ls
文件訪問(wèn)的模式有2種:文本模式(字符訪問(wèn),與編碼有關(guān))和二進(jìn)制模式(字節(jié)流訪問(wèn)猎荠,不管編碼)坚弱。不同模式下,操作函數(shù)不盡相同关摇,表現(xiàn)的結(jié)果也不一樣荒叶。
open的參數(shù)
mode模式
r read
只讀打開(kāi)文件,如果使用write方法會(huì)拋異常输虱。
如果文件不存在些楣,拋出FileNotFoundError異常
w write
表示只寫方式打開(kāi),如果讀取則拋出異常
如果文件不存在宪睹,則直接創(chuàng)建文件
如果文件存在愁茁,則清空文件內(nèi)容
w:沒(méi)有的話創(chuàng)建,有的話直接覆蓋
f = open('test','w')
f.close
以上兩行可以創(chuàng)建一個(gè)空文件
print后 會(huì)返回寫進(jìn)去的字符數(shù)量
x create
文件不存在直接創(chuàng)建亭病,并只寫方式打開(kāi)
文件已存在鹅很,會(huì)拋FileExistsError異常
a append
文件存在,只寫打開(kāi)罪帖,追加內(nèi)容
文件不存在促煮,則創(chuàng)建后邮屁,只寫打開(kāi),追加內(nèi)容菠齿。
總結(jié)以上幾種模式
r是只讀佑吝,wxa都是只寫。
wxa都可以產(chǎn)生新的文件泞当,w不管文件存在與否迹蛤,都會(huì)生成全新內(nèi)容的文件民珍;a不管文件是否存在襟士,都能在打開(kāi)的文件尾部追加;x必須要求文件事先不存在嚷量,自己造一個(gè)新文件陋桂。
文本模式t:操作單位是字符
字符流,將文件的字節(jié)按照某種字符編碼理解蝶溶,按照字符操作嗜历。open的默認(rèn)mode是rt
二進(jìn)制模式b:
字節(jié)流,將文件按照字節(jié)理解抖所,與字符編碼無(wú)關(guān)梨州。二進(jìn)制模式操作時(shí),字節(jié)操作使用bytes類型
一個(gè)文件讀取的編碼方式要和寫入時(shí)的編碼方式一致田轧,否則讀取時(shí)會(huì)出現(xiàn)亂碼暴匠。
二進(jìn)制操作寫入中文到文件中:
f = open('test3','wb')
#f.write('啊') #TypeError: a bytes-like object is required, not 'str' 需要像bytes一樣的東西,不要字符串
#f.write(b'啊') #bytes can only contain ASCII literal characters 只認(rèn)ASII傻粘,這樣寫不行
f.write('啊'.encode('gbk')) #encode 默認(rèn)編碼方式為 utf-8. 啊 用utf-8編碼占3個(gè)字節(jié):b'\xe5\x95\x8a' 漢字的正確編碼方式為gbk
f.close()
f = open('test3','r',encoding='gbk')
print(f.read())
f.close()
一般來(lái)講每窖,各種編碼都兼容ASII碼
各種編碼都是二進(jìn)制字節(jié)流去根據(jù)各自編碼表對(duì)應(yīng)不同的字符;二進(jìn)制字節(jié)流本身都是ASII碼弦悉。
+
+ 為r,w,a,x提供缺失的讀寫功能窒典,但是,獲取文件對(duì)象依舊按照r,w,a,x自己的特征稽莉。
+ 不能單獨(dú)使用瀑志,可以認(rèn)為它是為前面的模式字符做增強(qiáng)功能。
03-文件指針
文件指針:指向當(dāng)前字節(jié)位置
mode=r污秆,指針起始位置在0
mpde=a,指針起始位置在EOF
tell()顯示指針當(dāng)前位置
seek(offset[,whence]):移動(dòng)指針位置劈猪。offset偏移多少字節(jié),whence從哪里開(kāi)始混狠。
tell()和seek()都是針對(duì)字節(jié)的偏移岸霹,所以用他們處理字符流有風(fēng)險(xiǎn)
文本模式下:
- whence 0 缺省值,表示從頭開(kāi)始将饺,offset只能接受0和正整數(shù)
- whence 1 表示從當(dāng)前位置贡避,offset只接受0痛黎,相當(dāng)于原地不動(dòng),所以沒(méi)什么用
- whence 2 表示EOF開(kāi)始刮吧,offset只接受0湖饱,相當(dāng)于移動(dòng)文件指針到EOF。
- seek是按照字節(jié)偏移的杀捻。
- 文本模式下只支持從開(kāi)頭向后偏移的方式
二進(jìn)制模式下
- whence 0缺省值井厌,表示從頭開(kāi)始,offset只能是正整數(shù)致讥,包括0
- whence 1表示從當(dāng)前位置仅仆,offset可正可負(fù)
- whence 2表示從EOF開(kāi)始,offset可正可負(fù)
- 二進(jìn)制模式支持任意起點(diǎn)的偏移垢袱,從頭墓拜,從尾,從中間位置開(kāi)始请契。
- 向后seek可以超界咳榜,但是向前seek的時(shí)候,不能超界爽锥,否則會(huì)拋異常涌韩。
linux 下刪除一個(gè)文件的原理是將該文件的inode扔出去,讓別的文件使用氯夷,從而覆蓋掉改文件臣樱。
inode:索引節(jié)點(diǎn),它用來(lái)存放檔案及目錄的基本信息肠槽,包含時(shí)間擎淤、檔名、使用者及群組等秸仙。
04-緩沖區(qū)原理
緩存和緩沖的區(qū)別:
緩存:數(shù)據(jù)結(jié)構(gòu)為dict嘴拢,目的是快速找到想要的內(nèi)容
緩沖:數(shù)據(jù)結(jié)構(gòu)為list,一堆數(shù)據(jù)排隊(duì)放在那
04-緩沖區(qū)原理
buffering:緩沖區(qū)
- open的一個(gè)參數(shù)
- -1 表示使用缺省大小的buffer寂纪。
- 如果是二進(jìn)制模式席吴,使用io.DEFAULT_BUFFER_SIZE值,默認(rèn)是4096或者8192,目前多是8192 個(gè)字節(jié)捞蛋。
- 如果是文本模式:
- 如果是終端設(shè)備孝冒,是 行緩存方式
- 如果不是,則使用二進(jìn)制模式的策略拟杉。
- 0 只在二進(jìn)制模式使用庄涡,表示關(guān)閉buffer,即不需要內(nèi)存buffer搬设,可以看做是一個(gè)FIFO的文件穴店。
- 1 只在文本模式使用撕捍,表示使用行緩沖。意思是見(jiàn)到換行符就flush
- 大于1 用于指定buffer的大衅础忧风;但是在文本模式下,通過(guò)實(shí)驗(yàn)發(fā)現(xiàn)還是在用buffer的默認(rèn)值球凰。
buffer緩沖區(qū)
緩沖區(qū)是內(nèi)存中的一個(gè)連續(xù)的空間狮腿,一般來(lái)說(shuō)是一個(gè)FIFO(先進(jìn)先出)隊(duì)列(不支持中間插入,只支持兩頭操作)呕诉,到緩沖區(qū)滿了或者達(dá)到閾值缘厢,數(shù)據(jù)才會(huì)flush到磁盤。
內(nèi)存的運(yùn)行速度比I/O設(shè)備高的多
flush()將緩沖區(qū)的數(shù)據(jù)寫入磁盤
close()關(guān)閉前會(huì)調(diào)用flush()
內(nèi)存的東西不是能直接寫到磁盤上去的义钉,從內(nèi)存空間的用戶空間昧绣,搬到操作系的內(nèi)核空間,從內(nèi)核空間寫到磁盤緩沖區(qū)里捶闸,由磁盤緩沖區(qū)寫入磁盤
buffering 總結(jié)
一般說(shuō)來(lái)只需記得:
- 文本模式,一般都用默認(rèn)緩沖區(qū)大小
- 二進(jìn)制模式拖刃,是一個(gè)個(gè)字節(jié)的操作删壮,可以指定buffer的大小
- 一般來(lái)說(shuō),默認(rèn)緩沖區(qū)大小是個(gè)比較好的選擇兑牡,除非明確知道央碟,否則不調(diào)整它。
- 一般編程中均函,明確知道需要寫磁盤了亿虽,都會(huì)手動(dòng)調(diào)用一次flush(f.flash()),而不是等到自動(dòng)flush或者close的時(shí)候苞也。
05-編碼描述符及讀寫方法
encoding:編碼洛勉,僅文本模式使用
None表示使用缺省編碼,依賴操作系統(tǒng)如迟,windows下缺省GBK,linux下缺省UTF-8
UTF-8:用多個(gè)字節(jié)編碼世界上的所有文字收毫;大多數(shù)中文落在3個(gè)字節(jié)上
UTF-8(8-bit Unicode Transformation Format)是一種針對(duì)Unicode的可變長(zhǎng)度字符編碼,也是一種前綴碼殷勘,又稱萬(wàn)國(guó)碼此再。
GBK:?jiǎn)巫止?jié)+雙字節(jié)。ASCII單字節(jié)玲销,中文雙字節(jié)输拇;CODEPAGE=936 ,代表GBK
跨平臺(tái)的時(shí)候建議用UTF-8
GBK和UTF-8之間編碼不一致贤斜,需要查表
其他參數(shù)
errors
什么樣的編碼錯(cuò)誤將被捕獲
None和strict表示編碼錯(cuò)誤將拋出ValueError異常策吠;ignore表示忽略议慰。
一般都用默認(rèn),不用管奴曙。
newline
文本模式中換行的轉(zhuǎn)換别凹。可以為None,"空串洽糟、'\r'炉菲、'\n'、'\r\n'
讀時(shí)坤溃,None表示'\r'屯断、'\n'、'\r\n'都被轉(zhuǎn)換為'\n'
寫時(shí)卸耘,None表示'\n'都會(huì)被替換為系統(tǒng)卻省行分隔符os.linesep敞掘;
f = open("D:/magedu/test",'w')
f.write('py\rwww\nmaedu\r\npython3')
f.close()
newlines = [None,'','\n','\r\n']
for nl in newlines:
f = open("D:/magedu/test",'r+',newline=nl)
#print(f.readlines())
print(f.read().encode()) #通過(guò)編碼可以將換行符保留,而不是直接去做換行
f.close()
closefd
關(guān)閉文件描述符汁政,True表示關(guān)閉它道偷。False會(huì)在文件關(guān)閉后保持這個(gè)描述符。
fileobject.fileno()查看记劈。
f = open("D:/magedu/test",'w')
print(f.fileno()) #文件描述符
文件打開(kāi)時(shí)就會(huì)產(chǎn)生一個(gè)文件對(duì)象勺鸦。
read
read(size=-1)
size表示讀取的多少個(gè)字符或字節(jié);負(fù)數(shù)或者None表示讀取到EOF
f = open("D:/magedu/test",'w')
f.write('python\r\n123\r\npython3')
f.close()
f = open("D:/magedu/test",'r+')
print(f.read().encode()) #指針到最后
f.seek(0) #文件指針回到開(kāi)頭
print(f.readline(1).encode()) #一個(gè)個(gè)字符讀
f.close()
#以后讀取文件的每一行可以按照如下的讀目木,可以少寫一行
f = open("D:/magedu/test",'r')
for line in f:
print(line)
write
write(s),把字符串s寫入到文件中并返回字符的個(gè)數(shù)换途;常用
writelines(lines),將字符串列表寫入文件
要自己提供換行符
close
flush并關(guān)閉文件對(duì)象
文件已經(jīng)關(guān)閉,再次關(guān)閉沒(méi)有任何效果
其他
seekable() :是否可seek
readable():是否可讀
writable():是否可寫
closed 是否已經(jīng)關(guān)閉
f = open("D:/magedu/test",'r')
print(f.seekable()) # True
print(f.readable()) # True
print(f.writable()) # False
print(f.closed) # False
for line in f:
print(line)
f.close()
print(f.closed) # True
06-上下文管理
問(wèn)題的引出
在linux中執(zhí)行如下代碼:
lst = []
for _ in range(2000):
lst.append(open('test'))
#OSError:[Errorno 24] Too many open files:'test'
print(len(list))
lsof 列出打開(kāi)的文件刽射。沒(méi)有就 # yum install lsof
$lsof -p 1427|grep test|wc -l
lsof -p 進(jìn)程號(hào)
ulimit -a 查看所有限制军拟。其中open files 就是打開(kāi)文件數(shù)的限制,默認(rèn)1024