Python_IO編程

本篇文章將介紹python里面的I/O編程视事。更多內(nèi)容請(qǐng)參考:python學(xué)習(xí)指南

I/O編程

讀寫文件時(shí)最常見的IO操作礼旅。Python內(nèi)置了讀寫文件的函數(shù),用法和C是兼容的菲嘴。
讀寫文件前龄坪,我們必須了解一下健田,在磁盤上讀寫文件的功能都是由操作系統(tǒng)提供的妓局,現(xiàn)代操作系統(tǒng)不允許普通的程序直接操作磁盤呈宇,所以,讀寫文件就是請(qǐng)求操作系統(tǒng)打開一個(gè)文件對(duì)象(通常稱為文件描述符)存炮,然后穆桂,通過操作系統(tǒng)提供的接口從這個(gè)文件對(duì)象中讀取數(shù)據(jù)(讀文件),或者把數(shù)據(jù)寫入這個(gè)文件對(duì)象(寫文件)。

在I/O編程中享完,Stream(流)是一種重要的概念驼侠,分為輸入流(Input Stream)和輸入流(Output Stream)倒源。我們可以把流理解為一個(gè)水管句狼,一個(gè)負(fù)責(zé)輸入腻菇,一個(gè)負(fù)責(zé)輸出,這樣讀寫就可以實(shí)現(xiàn)同步糖耸。

文件讀寫

打開文件
讀寫文件是最常見的IO操作嘉竟。Python內(nèi)置了讀寫文件的函數(shù)舍扰,方便了文件的IO操作希坚。
文件讀寫之前需要打開文件,確定文件的讀寫模式个束。open函數(shù)用來打開文件播急,語法如下:

open(name[, mode[, buffering]])

open函數(shù)使用一個(gè)文件作為唯一的強(qiáng)制參數(shù)售睹,然后返回一個(gè)文件對(duì)象昌妹。模式(mode)和緩沖區(qū)(buffering)參數(shù)都是可選的,默認(rèn)模式是讀模式烂叔,默認(rèn)緩沖區(qū)是無蒜鸡。
如果文件不存在,open()函數(shù)就會(huì)拋出一個(gè)IOError錯(cuò)誤叶沛,并且給出錯(cuò)誤碼和詳細(xì)的信息告訴你文件不存在:

>>>f = open("user/michael/notfound.txt", "r")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
FileNotFoundError: [Errno 2] No such file or directory: 'user/michael/notfound.txt'

文件模式
open函數(shù)打開中的mode參數(shù)灰署,通過改變mode參數(shù)可以實(shí)現(xiàn)對(duì)文件的不同操作

功能描述
'r' 讀模式
'w' 寫模式
'a' 追加模式
'b' 二進(jìn)制模式(可添加到其它模式中使用)
'+' 讀/寫模式(可添加到其它模式中使用)

一般處理文本文件時(shí)溉箕,是用不到'b'參數(shù)的肴茄,但如果處理其它類型的文件(二進(jìn)制文件)独郎,比如mp3或者圖形氓癌,就應(yīng)該在模式中加上'b',這在爬蟲中處理媒體文件很常用贪婉。

文件緩沖區(qū)
open函數(shù)中第三個(gè)可選參數(shù)buffering控制著文件的緩沖疲迂。如果參數(shù)是0尤蒿,I/O操作就是無緩沖的幅垮,直接將數(shù)據(jù)寫到硬盤上;如果參數(shù)是1讳侨,I/O操作就是有緩沖的,數(shù)據(jù)先寫入到內(nèi)存里跨跨,只有使用flush函數(shù)或者close函數(shù)才會(huì)將數(shù)據(jù)更新到硬盤勇婴;如果參數(shù)大于1的數(shù)據(jù)則代表著緩沖區(qū)的大小(單位是字節(jié))咆耿,-1(或者任何負(fù)數(shù))代表使用默認(rèn)緩沖區(qū)的大小。

文件讀取
文件讀取主要分為按字節(jié)讀取和按行讀取愧驱,經(jīng)常用到的方法有read()椭盏、readline()掏颊、readlines()close()盆偿。

>>>f = open(r"c:\\text\\xiaoqi.txt", "r")
>>>f.read()   #調(diào)用read()方法可以一次性地將文件內(nèi)容全部讀到內(nèi)存中
'xiaoqi'
f.close()  #文件讀取完成后必須關(guān)閉

由于文件操作可能會(huì)出現(xiàn)IO異常事扭,一旦出現(xiàn)IO異常求橄,后面的close()
方法就不會(huì)調(diào)用罐农。所以為了保證程序的健壯性涵亏,我們需要使用try...finally來實(shí)現(xiàn)溯乒。

try
    f = open(r'c:\\text\\xiaoqi.txt')
    print(f.read())
finally:
    if f:
        f.close()

Python提供了一種更加簡(jiǎn)單有趣的寫法裆悄,使用with語句來替代try...finally代碼塊和close()方法

with open(r'c:\text\xiaoqi.txt') as fileReader:
    print(fileReader.read())

利用read()一次將文件內(nèi)容讀到內(nèi)存,但是如果文件過大或南,將會(huì)出現(xiàn)內(nèi)存不足的問題采够。一般對(duì)于大文件蹬癌,可以重復(fù)調(diào)用read(size)方法虹茶,一次最多讀取size個(gè)字節(jié)蝴罪。如果文件是文本文件要门,Python提供了更加合理的做法欢搜,調(diào)用了readline()可以每次讀取一行內(nèi)容撑毛,調(diào)用readlines()一次讀取所有內(nèi)容并按行返回列表唧领。大家可以根據(jù)自己的具體需求采取不同的讀取方式:

  1. 小文件可以直接采取read()方法讀到內(nèi)存;
  2. 大文件更加安全的方法是連續(xù)調(diào)用read(size);
  3. 面對(duì)于配置文件等文本文件斩个,使用readlines()方法更加合理
with open(r'c:\\text\\ss.txt') as fileReader:
    for line in fileReader.readlines():
        print(line.strip())

文件寫入
寫文件和讀文件是一樣的受啥,唯一的區(qū)別實(shí)在調(diào)用open方法時(shí)鸽心,傳入標(biāo)識(shí)符w或者wb表示寫入文本文件或者寫入二進(jìn)制文件顽频,示例如下:

f = open(r'c:\text\qie.txt', 'w')
f.write('xiaoqi')
f.close()

我們可以反復(fù)調(diào)用write()方法寫入文件太闺,最后必須使用close()方法來關(guān)閉文件糯景。使用write()方法的時(shí)候,操作系統(tǒng)不是立即將數(shù)據(jù)寫入文件中的省骂,而是先寫入內(nèi)存中緩存起來蟀淮,等到空閑時(shí)候再寫入文件中,最后使用close()方法就將數(shù)據(jù)完整地寫入文件中了钞澳。當(dāng)然也可以使用f.flush()方法怠惶,不斷地將數(shù)據(jù)立即寫入文件中,最后使用close()方法來關(guān)閉文件轧粟。和讀文件同樣道理策治,文件操作中可能會(huì)出現(xiàn)IO異常,所以還是推薦使用with語句:

with open(r'c:\text\csd.txt', 'w') as fileWriter:
    fileWriter.write('sdfs')

file-like Object

open()函數(shù)返回的這種有個(gè)read()方法的對(duì)象兰吟,在Python中統(tǒng)稱為file-like Object,除了file外,還可以是內(nèi)存的字節(jié)流,網(wǎng)路流料按,自定義流等。file-like Object不要求從特定類繼承,只要寫個(gè)read()方法就行。
StringIO就是內(nèi)存中創(chuàng)建的file-like Object,常用作臨時(shí)緩沖逃贝。

二進(jìn)制文件
一般我們用open()讀取的是文本文件,并且是UTF-8編碼的文本文件。要讀取二進(jìn)制文件卓起,比如圖片奕筐、視頻,就需要用rb模式打開文件:

f = open("/Users/michael/test.jpg", 'rb')
f.read()
b'\xff\xd8\xff\xe1\x00\x18Exif\x00\x00...' # 十六進(jìn)制表示的字節(jié)

字符編碼
要讀取非UTF-8編碼的文本文件,需要給open()函數(shù)傳入encoding參數(shù),例如,讀取GBK編碼的文件:

f = open("/Users/michael/gbk.text", "r", encoding="gbk")
f.read()
'測(cè)試'

遇到有些編碼不規(guī)范的文件,你可能會(huì)遇到UnicodeDecodeError遗座,因?yàn)樵谖谋疚募锌赡軍A雜了一些非法編碼的字符碎绎。遇到這種情況奸晴,open()函數(shù)還接收一個(gè)errors參數(shù)代箭,表示如果遇到編碼錯(cuò)誤后如何處理极景。最簡(jiǎn)單的方式是直接忽略:

f = open('/Users/michael/gbk.txt', 'r', encoding='gbk', errors='ignore')

StringIO
很多時(shí)候,數(shù)據(jù)讀寫并不一定是文件也可以在內(nèi)幕才能中讀寫。
StringIO顧名思義就是在內(nèi)存中讀寫str。
要把str寫入StringIO,我們需要先創(chuàng)建一個(gè)StringIO,然后睛竣,像文件一樣寫入即可:

>>>from io import StringIO
>>>f = StringIO()
>>>f.write('hello')
5
>>>f.write(" ")
1
>>>f.write("world!")
6
>>>print(f.getvalue())   #getvalue()方法用于獲得寫入后的str
'hello world!'

要讀取StringIO,可以用一個(gè)str初始哈StringIO,然后猖吴,像讀文件一樣讀裙睬:

>>>from io import StringIO
>>>f = StringIO("Hello!\nGoodbye!")
>>>while True:
    s = f.readline()
    if s == " ":
        break
    print(s.strip())
Hello!
Hi!
Goodbye

BytesIO
StringIO操作的只能是str,如果要操作二進(jìn)制數(shù)據(jù)矾削,就需要使用ByetsIO.
BytesIO實(shí)現(xiàn)了在內(nèi)存中讀寫bytes,我們創(chuàng)建了一個(gè)BytesIO,然后寫入一些bytes

>>>from io import BytesIO
>>>f = BytesIO()
>>>f.write('中文'.encode("utf-8"))
6
>>>print(f.getvalues)
b'\xe4\xb8\xad\xe6\x96\x87'

注意:寫入的不是str,而是經(jīng)過UTF-8編碼的bytes吝梅。
和StringIO類似做瞪,可以用一個(gè)bytes初始化BytesIO,然后牍帚,像讀文件一樣讀取:

>>>from io import BytesIO
>>>f = BytesIO(b'\xe4\xb8\xad\xa6\x96\x87')
>>>f.read()
b'\xe4\xb8\xad\xe6\x96\x87'

參考

  1. 廖雪峰-IO編程
  2. Python學(xué)習(xí)記錄之:IO編程
  3. Python中的str與unicode處理方法
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末咳燕,一起剝皮案震驚了整個(gè)濱河市聪蘸,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌设拟,老刑警劉巖万皿,帶你破解...
    沈念sama閱讀 216,692評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件惩系,死亡現(xiàn)場(chǎng)離奇詭異妙黍,居然都是意外死亡拭嫁,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來涨薪,“玉大人创橄,你說我怎么就攤上這事咖熟÷奚樱” “怎么了谊路?”我有些...
    開封第一講書人閱讀 162,995評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)菩彬。 經(jīng)常有香客問我缠劝,道長(zhǎng),這世上最難降的妖魔是什么骗灶? 我笑而不...
    開封第一講書人閱讀 58,223評(píng)論 1 292
  • 正文 為了忘掉前任剩彬,我火速辦了婚禮,結(jié)果婚禮上矿卑,老公的妹妹穿的比我還像新娘喉恋。我一直安慰自己,他們只是感情好母廷,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,245評(píng)論 6 388
  • 文/花漫 我一把揭開白布轻黑。 她就那樣靜靜地躺著,像睡著了一般琴昆。 火紅的嫁衣襯著肌膚如雪氓鄙。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,208評(píng)論 1 299
  • 那天业舍,我揣著相機(jī)與錄音抖拦,去河邊找鬼。 笑死舷暮,一個(gè)胖子當(dāng)著我的面吹牛态罪,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播下面,決...
    沈念sama閱讀 40,091評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼复颈,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了沥割?” 一聲冷哼從身側(cè)響起耗啦,我...
    開封第一講書人閱讀 38,929評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎机杜,沒想到半個(gè)月后帜讲,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,346評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡椒拗,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,570評(píng)論 2 333
  • 正文 我和宋清朗相戀三年似将,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了获黔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,739評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡玩郊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出枉阵,到底是詐尸還是另有隱情译红,我是刑警寧澤,帶...
    沈念sama閱讀 35,437評(píng)論 5 344
  • 正文 年R本政府宣布兴溜,位于F島的核電站侦厚,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏拙徽。R本人自食惡果不足惜刨沦,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,037評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望膘怕。 院中可真熱鬧想诅,春花似錦、人聲如沸岛心。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)忘古。三九已至徘禁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間髓堪,已是汗流浹背送朱。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留干旁,地道東北人驶沼。 一個(gè)月前我還...
    沈念sama閱讀 47,760評(píng)論 2 369
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像争群,于是被迫代替她去往敵國(guó)和親商乎。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,647評(píng)論 2 354

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

  • 文件讀寫 讀寫文件是最常見的IO操作祭阀。Python內(nèi)置了讀寫文件的函數(shù)鹉戚,用法和C是兼容的。由于文件讀寫時(shí)都有可能產(chǎn)...
    時(shí)間之友閱讀 466評(píng)論 0 0
  • pyton review 學(xué)習(xí)指南 https://www.zhihu.com/question/29138020...
    孫小二wuk閱讀 1,046評(píng)論 0 2
  • IO編程概念 IO在計(jì)算機(jī)中指Input/Output专控,也就是輸入和輸出抹凳。由于程序和運(yùn)行時(shí)數(shù)據(jù)是在內(nèi)存中駐留,由C...
    時(shí)間之友閱讀 724評(píng)論 0 0
  • 文件讀寫 讀文件由于文件讀寫時(shí)都有可能產(chǎn)生IOError伦腐,一旦出錯(cuò)赢底,后面的f.close()就不會(huì)調(diào)用。所以,為了...
    carolwhite閱讀 173評(píng)論 0 0
  • 我們看書幸冻,總是從一本書的最高境界來欣賞和品評(píng)粹庞。我們使用繩子,總是從最薄弱的一段來斷定繩子的質(zhì)量洽损。坐冷板凳的書呆子庞溜,...
    風(fēng)中的半只煙閱讀 97評(píng)論 0 0