第五章:文件和I/O

任何程序都需要處理輸入和輸出。本章節(jié)介紹了處理各種不同類型文件時(shí)的慣用方法,包括文本和二進(jìn)制人間的處理,文件的編碼以及其他的一些相關(guān)內(nèi)容。

1.讀寫文本數(shù)據(jù)

>>>with open ('somefile.txt','rt') as f:
>>>    data = f.read()
>>>#Write chunks of text data
>>>with open('somefile.txt','wt') as f:
>>>    f.write(text1)
>>>    f.write(text2)

類似地,要對(duì)文本文件執(zhí)行寫入操作,可以使用open()函數(shù)的wt模式來完成,如果待操作的文件已經(jīng)存在,那么這回清除并覆蓋其原先的內(nèi)容;

如果要在已存在的文件的結(jié)尾處追加內(nèi)容,可以使用open()函數(shù)的at模式;

  • 一般來說,讀寫文本文件都是非常簡(jiǎn)單直接的,但是,這里了還是有幾個(gè)微妙的細(xì)節(jié)需要引起注意;首先,我們?cè)趯?shí)例中采用了with語句,這會(huì)為使用的文件創(chuàng)建一個(gè)上下文環(huán)境,當(dāng)程序的控制流離開with語快后,文件將會(huì)自動(dòng)關(guān)閉;我們并不一定要用with語句,但是如果我們不用的話請(qǐng)確保要記得手動(dòng)關(guān)閉文件;
>>>f = open('somefile.txt','rt')
>>>data = f.read()
>>>f.close()
  • 關(guān)于默認(rèn)換行符,open()函數(shù)提供了一個(gè)newline=''的參數(shù);
    with open('somefile.txt','rt',newline = '') as f:

  • 關(guān)于文本文件中可能出現(xiàn)的編碼錯(cuò)誤,當(dāng)encoding = 'utf-8';
    UnicodeDecodeError:'ascii' codec can't decode byte 0xc3 in position
    如果遇到這樣的錯(cuò)誤,這通常表示沒有一正確的編碼方式來讀取文件??梢允褂胑ncoding來制定不同的編碼方式;如果還不能避免的話,則可以為open()函數(shù)提供一個(gè)可選的errors參數(shù)來慘厲錯(cuò)誤;

>>>#Replace bad chars with Unicode U+fffd replacement char
>>>f = open(somefile.txt','rt',encoding = 'ascii',errors = 'replace')
>>>f.read()
'Spicy Jalape?o'
>>>#Replace bad chars entirely
>>>f = open(somefile.txt','rt',encoding = 'ascii',errors = 'ignore')
>>>f.read()
'Spicy Jalapeo'

如果常常在擺弄open()函數(shù)的encoding和errors參數(shù),并為此做了大量的技巧性操作,那就適得其反了;因?yàn)樯畋静粦?yīng)該如此艱難,關(guān)于文本,第一條守則就是只需要確??偸鞘褂谜_的文本編碼形式即可;請(qǐng)使用默認(rèn)的編碼設(shè)定(通常utf-8)

2.將輸出重定向到文件中

問題:我們想把print()函數(shù)的輸出重定向到一個(gè)文件中。

解決方案:我們只需要在print()函數(shù)加上file關(guān)鍵字參數(shù)即可;

>>>with open('somefile.txt','rt') as f:
>>>    print("hello world!",f)

3.以不同的分隔符或行結(jié)尾完成打印

問題:我們想通過print()函數(shù)輸出數(shù)據(jù),但是同時(shí)也希望修改分隔符或者行結(jié)尾符

解決方案:可以在print()函數(shù)中使用sep和end關(guān)鍵字參數(shù)來根據(jù)需要修改輸出;

>>> print('ACME',50,90.4)
ACME 50 90.4
>>> print('ACME',50,90.4,sep=',')
ACME,50,90.4
>>> print('ACME',50,90.4,sep=',',end='!!\n')
ACME,50,90.4!!

我們可以使用end參數(shù)在輸出中禁止打印出換行符的方式:

>>> for i in range(5):
...     print(i)
...
0
1
2
3
4
>>> for i in range(5):
...     print(i,end=' ')
...
0 1 2 3 4 >>>

str.join 問題也可以處理簡(jiǎn)單的字符分隔文本問題;

>>> row = ('ACME',50,91.5)
>>> print(','.join(row))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: sequence item 1: expected str instance, int found
>>> print(','.join(str(w) for w in row))
ACME,50,91.5

更加高效的方法:

>>> print(*row,sep = ',')
ACME,50,91.5

4.對(duì)鞋二進(jìn)制數(shù)據(jù)

解決方案:使用open()函數(shù)的rb模式或者wb模式就可以實(shí)現(xiàn)對(duì)二進(jìn)制數(shù)據(jù)的讀或者寫;

5.對(duì)已不存在的文件執(zhí)行寫入操作

問題:我們想將數(shù)據(jù)寫入到一個(gè)文件中,但只當(dāng)該文件已經(jīng)不在文件系統(tǒng)中時(shí)才這么做;

解決方案:這個(gè)問題可以通過使用open()函數(shù)中鮮為人知的x模式替換常見的w模式來解決

>>> with open('d:\\tmp.txt','wt') as f:
...     f.write("Hello\n")
...
6
>>> with open('d:\\tmp.txt','xt') as f:
...     f.write("Hello\n")
...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
FileExistsError: [Errno 17] File exists: 'd:\\tmp.txt'

如果文件時(shí)二進(jìn)制模式,那么用xb替代xt即可;

6.在字符串上執(zhí)行I/O操作

7.讀寫壓縮的數(shù)據(jù)文件

問題:我們需要讀寫以gzip、bz2格式壓縮的文件中的數(shù)據(jù):

解決方案:gzip、bz2,模塊使得同這類壓縮型文件打交道變得非常簡(jiǎn)單,這兩個(gè)模塊都提供了open()的其他實(shí)現(xiàn),可用于處理壓縮文件;

#gzip compression
>>>import gzip
>>>with gzip.open('somefile.gz','rt') as f:
>>>    text = f.read()

#bz2 compression
>>>import bz2
>>>with bz2.open('somefile.bz2','rt') as f:
>>>    text = f.read()

對(duì)應(yīng)的寫入文件也相似;
大部分情況下讀寫壓縮數(shù)據(jù)都是簡(jiǎn)單而直接的,單請(qǐng)注意,選擇正確的文件模式是至關(guān)重要的。如果沒有指定的模式,那么默認(rèn)的模式是二進(jìn)制,這會(huì)使得期望接受文本的程序奔潰。gzip.open()和bz2.open()所接受的參數(shù)和內(nèi)建的open()函數(shù)一樣,也支持encoding,newline,errors等關(guān)鍵字參數(shù);
當(dāng)寫入壓縮數(shù)據(jù)時(shí),壓縮級(jí)別可以通過compresslevel關(guān)鍵字參數(shù)來指定,這是可選的;

>>>with gzip.open('somefile.gz','wt',compresslevel = 5) as f:
>>>    f.write(text)

默認(rèn)級(jí)別是9,代表著最高的壓縮等級(jí)。低等級(jí)的壓縮可帶來更好的性能表現(xiàn),但壓縮比就沒那么大;

8.對(duì)固定大小的記錄進(jìn)行迭代

9.將二進(jìn)制數(shù)據(jù)兌取到可變緩沖區(qū)中

10.對(duì)二進(jìn)制文件做內(nèi)存映射

11.處理路徑名

問題:我們需要處理路徑名以找出基文件名,目錄名,絕對(duì)路徑等相關(guān)信息;

解決方案:要操作路徑名,可以使用os.path模塊中的函數(shù)

>>> import os
>>> path = "D:\ostext\meizitu\mzt01\\10a33.jpg"
>>> os.path.basename(path)
'10a33.jpg'
>>> os.path.dirname(path)
'D:\\ostext\\meizitu\\mzt01'
>>> os.path.join('tmp','data',os.path.basename(path))
'tmp\\data\\10a33.jpg'
>>> os.path.expanduser(path)
'D:\\ostext\\meizitu\\mzt01\\10a33.jpg'
#分離擴(kuò)展名
>>> os.path.splitext(path)
('D:\\ostext\\meizitu\\mzt01\\10a33', '.jpg')

一、python中對(duì)文件、文件夾操作時(shí)經(jīng)常用到的os模塊和shutil模塊常用方法。
1.得到當(dāng)前工作目錄,即當(dāng)前Python腳本工作的目錄路徑: os.getcwd()
2.返回指定目錄下的所有文件和目錄名:os.listdir()
3.函數(shù)用來刪除一個(gè)文件:os.remove()
4.刪除多個(gè)目錄:os.removedirs(r“c:\python”)
5.檢驗(yàn)給出的路徑是否是一個(gè)文件:os.path.isfile()
6.檢驗(yàn)給出的路徑是否是一個(gè)目錄:os.path.isdir()
7.判斷是否是絕對(duì)路徑:os.path.isabs()
8.檢驗(yàn)給出的路徑是否真地存:os.path.exists()
9.返回一個(gè)路徑的目錄名和文件名:os.path.split() eg os.path.split('/home/swaroop/byte/code/poem.txt') 結(jié)果:('/home/swaroop/byte/code', 'poem.txt')
10.分離擴(kuò)展名:os.path.splitext()
11.獲取路徑名:os.path.dirname()
12.獲取文件名:os.path.basename()
13.運(yùn)行shell命令: os.system()
14.讀取和設(shè)置環(huán)境變量:os.getenv() 與os.putenv()
15.給出當(dāng)前平臺(tái)使用的行終止符:os.linesep Windows使用'\r\n',Linux使用'\n'而Mac使用'\r'
16.指示你正在使用的平臺(tái):os.name 對(duì)于Windows,它是'nt',而對(duì)于Linux/Unix用戶,它是'posix'
17.重命名:os.rename(old, new)
18.創(chuàng)建多級(jí)目錄:os.makedirs(r“c:\python\test”)
19.創(chuàng)建單個(gè)目錄:os.mkdir(“test”)
20.獲取文件屬性:os.stat(file)
21.修改文件權(quán)限與時(shí)間戳:os.chmod(file)
22.終止當(dāng)前進(jìn)程:os.exit()
23.獲取文件大?。簅s.path.getsize(filename)



glob是python自己帶的一個(gè)文件操作相關(guān)模塊,內(nèi)容也不多,用它可以查找符合自己目的的文件,就類似于Windows下的文件搜索,而且也支持通配符,,?,[]這三個(gè)通配符,代表0個(gè)或多個(gè)字符,?代表一個(gè)字符,[]匹配指定范圍內(nèi)的字符,如[0-9]匹配數(shù)字。

它的主要方法就是glob,該方法返回所有匹配的文件路徑列表,該方法需要一個(gè)參數(shù)用來指定匹配的路徑字符串(本字符串可以為絕對(duì)路徑也可以為相對(duì)路徑),比如:

#我這里就是獲得C盤下的所有txt文件
>>>import glob
>>>glob.glob(r'c:/*.txt')

#獲得指定目錄下的所有jpg文件
glob.glob(r'E:/pic/*/*.jpg')

iglob方法

獲取一個(gè)可編歷對(duì)象, 使用它可以逐個(gè)獲取匹配的文件路徑名。與glob.glob()的區(qū)別是:glob.glob同時(shí)獲取所有的匹配路徑,而 glob.iglob一次只獲取一個(gè)匹配路徑。這有點(diǎn)類似于.NET中操作數(shù)據(jù)庫用到的DataSet與DataReader。下面是一個(gè)簡(jiǎn)單的例子:

import glob     
#父目錄中的.py文件  
f = glob.iglob(r'../*.py')  


12.檢測(cè)文件是否存在

>>>os.path.exists('/etc/passwd')
True
>>>os.path.exists('/etc/spam')
False

#
>>>os.path.isfile('/etc/passwd')
>>>os.path.isdir('/etc/passwd')
>>>os.path.islink('/etc/passwd')
>>>os.path.realpath('/etc/passwd')

#
>>> os.path.getsize(path)
100714
>>> os.path.getmtime(path)
1512957742.67442
>>> import time
>>> time.ctime(os.path.getmtime(path))
'Mon Dec 11 10:02:22 2017'

13.獲取目錄內(nèi)容的內(nèi)部

解決方案:可以使用os.listdir()函數(shù)來獲取目錄中的文件列表;

>>>import os
>>>names = os.listdir(path)

字符串的startswith()和endswith()方法對(duì)于篩選目錄中的內(nèi)容也同樣有用;
至于文件名的匹配??梢允褂胓lob或者fnmatch()模塊;

>>>import glob
>>>pyfiles = glob.glob('somedir/*.py')
#
>>>from fnmatch import fnmatch
>>>pyfiles = [name for name in os.listdir('somedir')]
>>>    if fnmatch(name,'*.py')

14.繞過文件名編碼

15.打印無法解碼的文件

16.為已經(jīng)打開的文件添加或修改編碼方式

17.將字節(jié)寫入到文本文件

18.將已有的文件描述符包裝為文件對(duì)象

19.創(chuàng)建臨時(shí)文件和目錄

20.同串口進(jìn)行通信

21.序列化Python對(duì)象

問題:我們需要將Python對(duì)象序列化為字節(jié)流,這樣就可以保存到文件中,存儲(chǔ)到數(shù)據(jù)庫中或者通過網(wǎng)絡(luò)連接進(jìn)行傳輸;

解決方案:序列化數(shù)據(jù)最常見的做法就是使用pickle模塊,其中:要將某個(gè)對(duì)象轉(zhuǎn)存儲(chǔ)到文件中,可以舒勇pickle.dump();如果要從字節(jié)流中創(chuàng)建出對(duì)象,可以使用peckle.load()或者pickle.loads()函數(shù);

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,551評(píng)論 19 139
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,007評(píng)論 25 709
  • linux資料總章2.1 1.0寫的不好抱歉 但是2.0已經(jīng)改了很多 但是錯(cuò)誤還是無法避免 以后資料會(huì)慢慢更新 大...
    數(shù)據(jù)革命閱讀 13,229評(píng)論 2 33
  • lumicinta閱讀 366評(píng)論 0 0
  • 近兩天ps軍人形象的人老多,可憐孩子,丑人多作怪不是,p的不像自己就是好看?你得多嫌棄你自己? 爹媽給的就是世界上...
    縱情嬉戲天地間閱讀 328評(píng)論 0 0

友情鏈接更多精彩內(nèi)容