Python中文件I/O高效操作處理的技巧分享
如何讀寫文本文件?
實際案例
某文本文件編碼格式已直(如UTF-8,GBK,BIG5),在python2.x和python3.x中分別如何讀取這些文件?
解決方案
字符串的語義發(fā)生了變化:
python2 | python3 |
---|---|
str | bytes |
unicode | str |
python2.x 寫入文件前對 unicode 編碼,讀入文件后對二進制字符串解碼
>>> f = open('py2.txt', 'w') >>> s = u'你好' >>> f.write(s.encode('gbk')) >>> f.close() >>> f = open('py2.txt', 'r') >>> t = f.read() >>> print t.decode('gbk') 你好
python3.x 中 open 函數(shù)指定 t 的文本模式, encoding 指定編碼格式
>>> f = open('py3.txt', 'wt', encoding='utf-8') >>> f.write('你好') 2 >>> f.close() >>> f = open('py3.txt', 'rt', encoding='utf-8') >>> s = f.read() >>> s '你好'
如何設(shè)置文件的緩沖
實際案例
將文件內(nèi)容寫入到硬盤設(shè)備時,使用系統(tǒng)調(diào)用,這類I/O操作的時間很長,為了減少I/O操作的次數(shù),文件通常使用緩沖區(qū)(有足夠多的數(shù)據(jù)才進行系統(tǒng)調(diào)用),文件的緩存行為,分為全緩沖、行緩存、無緩沖。
如何設(shè)置Python中文件對象的緩沖行文?
解決方案
全緩沖: open 函數(shù)的 buffering 設(shè)置為大于1的整數(shù)n,n為緩沖區(qū)大小
>>> f = open('demo2.txt', 'w', buffering=2048) >>> f.write('+' * 1024) >>> f.write('+' * 1023) # 大于2048的時候就寫入文件 >>> f.write('-' * 2) >>> f.close()
行緩沖: open 函數(shù)的 buffering 設(shè)置為1
>>> f = open('demo3.txt', 'w', buffering=1) >>> f.write('abcd') >>> f.write('1234') # 只要加上\n就寫入文件中 >>> f.write('\n') >>> f.close()
無緩沖: open 函數(shù)的 buffering 設(shè)置為0
>>> f = open('demo4.txt', 'w', buffering=0) >>> f.write('a') >>> f.write('b') >>> f.close()
如何將文件映射到內(nèi)存?
實際案例
- 在訪問某些二進制文件時,希望能把文件映射到內(nèi)存中,可以實現(xiàn)隨機訪問.(framebuffer設(shè)備文件)
- 某些嵌入式設(shè)備,寄存器唄編址到內(nèi)存地址空間,我們可以映射 /dev/mem 某范圍,去訪問這些寄存器
- 如果多個進程映射到同一個文件,還能實現(xiàn)進程通信的目的
解決方案
使用標準庫中的 mmap 模塊的 mmap()
函數(shù),它需要一個打開的文件描述符作為參數(shù)
創(chuàng)建如下文件
[root@iZ28i253je0Z ~]# dd if=/dev/zero of=demo.bin bs=1024 count=1024 1024+0 records in 1024+0 records out 1048576 bytes (1.0 MB) copied, 0.00380084 s, 276 MB/s # 以十六進制格式查看文件內(nèi)容 [root@iZ28i253je0Z ~]# od -x demo.bin 0000000 0000 0000 0000 0000 0000 0000 0000 0000 * 4000000
>>> import mmap >>> import os >>> f = open('demo.bin','r+b') # 獲取文件描述符 >>> f.fileno() 3 >>> m = mmap.mmap(f.fileno(),0,access=mmap.ACCESS_WRITE) >>> type(m) <type 'mmap.mmap'> # 可以通過索引獲取內(nèi)容 >>> m[0] '\x00' >>> m[10:20] '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' # 修改內(nèi)容 >>> m[0] = '\x88'
查看
[root@iZ28i253je0Z ~]# od -x demo.bin 0000000 0088 0000 0000 0000 0000 0000 0000 0000 0000020 0000 0000 0000 0000 0000 0000 0000 0000 * 4000000
修改切片
>>> m[4:8] = '\xff' * 4
查看
[root@iZ28i253je0Z ~]# od -x demo.bin 0000000 0088 0000 ffff ffff 0000 0000 0000 0000 0000020 0000 0000 0000 0000 0000 0000 0000 0000 * 4000000 >>> m = mmap.mmap(f.fileno(),mmap.PAGESIZE * 8,access=mmap.ACCESS_WRITE,offset=mmap.PAGESIZE * 4) >>> m[:0x1000] = '\xaa' * 0x1000
查看
[root@iZ28i253je0Z ~]# od -x demo.bin 0000000 0088 0000 ffff ffff 0000 0000 0000 0000 0000020 0000 0000 0000 0000 0000 0000 0000 0000 * 0040000 aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa * 0050000 0000 0000 0000 0000 0000 0000 0000 0000 * 4000000
如何訪問文件的狀態(tài)?
實際案例
在某些項目中,我們需要獲得文件狀態(tài),例如:
- 文件的類型(普通文件、目錄、符號鏈接、設(shè)備文件…)
- 文件的訪問權(quán)限
- 文件的最后的訪問/修改/節(jié)點狀態(tài)更改時間
- 普通文件的大小
- …..
解決方案
當(dāng)前目錄有如下文件
[root@iZ28i253je0Z 2016-09-16]# ll total 4 drwxr-xr-x 2 root root 4096 Sep 16 11:35 dirs -rw-r--r-- 1 root root 0 Sep 16 11:35 files lrwxrwxrwx 1 root root 37 Sep 16 11:36 lockfile -> /tmp/qtsingleapp-aegisG-46d2-lockfile
系統(tǒng)調(diào)用
標準庫中的os模塊下的三個系統(tǒng)調(diào)用 stat 、 fstat 、 lstat 獲取文件狀態(tài)
>>> import os >>> s = os.stat('files') >>> s posix.stat_result(st_mode=33188, st_ino=267646, st_dev=51713L, st_nlink=1, st_uid=0, st_gid=0, st_size=0, st_atime=1473996947, st_mtime=1473996947, st_ctime=1473996947) >>> s.st_mode 33188 >>> import stat # stat有很多S_IS..方法來判斷文件的類型 >>> stat.S_ISDIR(s.st_mode) False # 普通文件 >>> stat.S_ISREG(s.st_mode) True
獲取文件的訪問權(quán)限,只要大于0就為真
>>> s.st_mode & stat.S_IRUSR 256 >>> s.st_mode & stat.S_IXGRP 0 >>> s.st_mode & stat.S_IXOTH 0
獲取文件的修改時間
# 訪問時間 >>> s.st_atime 1473996947.3384445 # 修改時間 >>> s.st_mtime 1473996947.3384445 # 狀態(tài)更新時間 >>> s.st_ctime 1473996947.3384445
將獲取到的時間戳進行轉(zhuǎn)換
>>> import time >>> time.localtime(s.st_atime) time.struct_time(tm_year=2016, tm_mon=9, tm_mday=16, tm_hour=11, tm_min=35, tm_sec=47, tm_wday=4, tm_yday=260, tm_isdst=0)
獲取普通文件的大小
>>> s.st_size 0
快捷函數(shù)
標準庫中 os.path 下的一些函數(shù),使用起來更加簡潔
文件類型判斷
>>> os.path.isdir('dirs') True >>> os.path.islink('lockfile') True >>> os.path.isfile('files') True
文件三個時間
>>> os.path.getatime('files') 1473996947.3384445 >>> os.path.getmtime('files') 1473996947.3384445 >>> os.path.getctime('files') 1473996947.3384445
獲取文件大小
>>> os.path.getsize('files') 0
如何使用臨時文件?
實際案例
某項目中,我們從傳感器采集數(shù)據(jù),每收集到1G數(shù)據(jù)后,做數(shù)據(jù)分析,最終只保存分析結(jié)果,這樣很大的臨時數(shù)據(jù)如果常駐內(nèi)存,將消耗大量內(nèi)存資源,我們可以使用臨時文件存儲這些臨時數(shù)據(jù)(外部存儲)
臨時文件不用命名,且關(guān)閉后會自動被刪除
解決方案
使用標準庫中的 tempfile 下的 TemporaryFile, NamedTemporaryFile
>>> from tempfile import TemporaryFile, NamedTemporaryFile # 訪問的時候只能通過對象f來進行訪問 >>> f = TemporaryFile() >>> f.write('abcdef' * 100000) # 訪問臨時數(shù)據(jù) >>> f.seek(0) >>> f.read(100) 'abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd'
>>> ntf = NamedTemporaryFile() # 如果要讓每次創(chuàng)建NamedTemporaryFile()對象時不刪除文件,可以設(shè)置NamedTemporaryFile(delete=False) >>> ntf.name # 返回當(dāng)前臨時文件在文件系統(tǒng)中的路徑 '/tmp/tmppNvBu2'
總結(jié)
以上就是關(guān)于Python中文件I/O高效處理技巧的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作能帶來一定的幫助,如果有疑問大家可以留言交流。
相關(guān)文章
python導(dǎo)入csv文件出現(xiàn)SyntaxError問題分析
這篇文章主要介紹了python導(dǎo)入csv文件出現(xiàn)SyntaxError問題分析,同時涉及python導(dǎo)入csv文件的三種方法,具有一定借鑒價值,需要的朋友可以參考下。2017-12-12Python+fuzzywuzzy計算兩個字符串之間的相似度
fuzzywuzzy?可以計算兩個字符串之間的相似度,它依據(jù)?Levenshtein?Distance?算法來進行計算,該算法又叫?Edit?Distance?算法,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2022-09-09Python使用Opencv實現(xiàn)邊緣檢測以及輪廓檢測的實現(xiàn)
這篇文章主要介紹了Python使用Opencv實現(xiàn)邊緣檢測以及輪廓檢測的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12python實現(xiàn)將讀入的多維list轉(zhuǎn)為一維list的方法
今天小編就為大家分享一篇python實現(xiàn)將讀入的多維list轉(zhuǎn)為一維list的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-06-06