Python升级之路( Lv9 ) 文件操作
Python系列文章目錄
第一章 Python 入門
第二章 Python基本概念
第三章 序列
第四章 控制語句
第五章 函數
第六章 面向對象基礎
第七章 面向對象深入
第八章 異常機制
第九章 文件操作
文件操作
- Python系列文章目錄
- 前言
- 一、什么是文件操作
- 1. 文件分類
- 2. 常用編碼
- ASCII
- GBK
- Unicode
- UTF-8
- 二、文件操作
- 1. 創建文件對象
- 2. 文件的寫入
- 基本文件的寫入操作
- 中文亂碼
- 代碼編寫時
- 控制臺輸出時
- write()/writelines()寫入數據
- close()關閉文件流
- with語句(上下文管理器)
- 3. 文件的讀取
- 二進制文件的讀取和寫入
- 4. 文件對象的常用屬性和方法
- 文件任意位置操作
- 三、文件操作拓展模塊
- 1. pickle序列化模塊
- 2. csv文件的操作
- csv文件讀取
- csv文件寫入
- 3. os和os.path模塊
- os模塊-調用操作系統命令
- os模塊-文件和目錄操作
- os.path模塊
- walk()遞歸遍歷所有文件和目錄
- 遞歸遍歷目錄下所有文件
- 4. shutil模塊(拷貝和壓縮)
前言
在本章節, 主要介紹了文件操作相關的API方法使用
首先我們將會學習什么是文件操作, 以及文件分類還有在IO操作時會用到的常用編碼介紹
然后我們學習了文件操作的流程, 創建->寫入->關閉
在然后我們學習了文件的拓展, 序列化模塊pickle, 文件操作模塊csv, 系統操作調用模塊os和os.path以及文件拷貝壓縮模塊shutil
一、什么是文件操作
一個完整的程序一般都包括數據的存儲和讀取;我們在前面寫的程序數據都沒有進行實際的存儲,因此python解釋器執行完數據就消失了
實際開發中,我們經常需要從外部存儲介質(硬盤、光盤、U盤等)讀取數據,或者將程序產生的數據存儲到文件中,實現“持久化”保存
1. 文件分類
按文件中數據組織形式,我們把文件分為文本文件和二進制文件兩大類:
文本文件
文本文件存儲的是普通“字符”文本,python默認為 unicode 字符集,可以使用記事本程序打開
二進制文件
二進制文件把數據內容用“字節”進行存儲,無法用記事本打開, 必須使用專用的軟件解碼.
常見的有:MP4視頻文件、MP3音頻文件、JPG圖片、doc文檔等等
2. 常用編碼
在操作文本文件時,經常會操作中文,這時候就經常會碰到亂碼問題.
為了解決中文亂碼問題,需要學習下各個編碼之前的問題.
常用編碼之間的關系如下:
ASCII
全稱為 American Standard Code for Information Interchange ,美國信息交換標準代碼,
這是世界上最早最通用的單字節編碼系統,主要用來顯示現代英語及其他西歐語言
注意事項:
- ASCII 碼用7位表示,只能表示128個字符. 只定義了2^7=128個字符,用7bit即可完全編碼,
而一字節8bit的容量是256,所以一字節 ASCII 的編碼最高位總是0 - ASCll 碼對應碼表如下: ASCll 碼表
GBK
GBK即漢字內碼擴展規范,英文全稱Chinese Internal Code Specification.
GBK編碼標準兼容GB2312,共收錄漢字21003個、符號883個,并提供1894個造字碼位,簡、繁體字融于一庫。
GBK采用雙字節表示,總體編碼范圍為8140-FEFE,首字節在81-FE 之間,尾字節在40-FE 之間
Unicode
Unicode 編碼設計成了固定兩個字節,所有的字符都用16位2^16=65536表示,包括之前只占8位的英文字符等,所以會造成空間的浪費
Unicode 完全重新設計,不兼容 iso8859-1 ,也不兼容任何其他編碼
UTF-8
對于英文字母, unicode 也需要兩個字節來表示, 所以 unicode 不便于傳輸和存儲.
因此而產生了 UTF編碼 , UTF-8 全稱是( 8-bit UnicodeTransformation Format )
注意事項
- UTF 編碼兼容 iso8859-1 編碼,同時也可以用來表示所有語言的字符
- UTF 編碼是不定長編碼,每一個字符的長度從1-4個字節不等.
英文字母都是用一個字節表示,而漢字使用三個字節 - 一般項目都會使用 UTF-8
我們之所以傾向于使用UTF-8 , 是因為其不定長編碼可以在節省內存的同時能夠完全兼容中文
二、文件操作
1. 創建文件對象
open() 函數用于創建文件對象,基本語法格式如下: open(文件名[,打開方式])
注意:
-
如果只是文件名,代表在當前目錄下的文件. 文件名可以錄入全路徑,比如: D:\a\b.txt
可以使用原始字符串 r“d:\b.txt” 減少 \ 的輸入, 因此以上代碼可改寫成 f = open(r"d:\b.txt","w") -
作為入參的打開方式如下(經常會用!!!)
-
文本文件對象和二進制文件對象的創建
如果是二進制模式 b ,則創建的是二進制文件對象,處理的基本單元是“字節”
如果沒有增加模式 b ,則默認創建的是文本文件對象,處理的基本單元是“字符”
2. 文件的寫入
文本文件的寫入一般就是三個步驟:
- 創建文件對象
- 寫入數據
- 關閉文件對象
基本文件的寫入操作
實操代碼
# 1.使用open()方式 f = open(r"d:\a.txt", "a") s = "TimePause\n時間靜止\n" f.write(s) f.close()結果展示
中文亂碼
代碼編寫時
windows 操作系統默認的編碼是 GBK , Linux 操作系統默認的編碼是 UTF- 8 .
當我們用 open() 時,調用的是操作系統相關api來打開的文件,并且默認的編碼是 GBK
但是由于我們通常習慣將所有代碼編碼都設置成 UTF- 8 ., 因此在打開時會出現亂碼問題, 如下圖所示
解決方案:
按照上圖提示, 將文本編碼設置成 GBK格式讀取即可
注意:
我們還可以通過指定編碼來解決中文亂碼問題. 因為我們將pycharm文本讀寫編碼都設置成 utf-8,
因此只要我們在文件寫入的時候規定編碼為 utf-8(默認gbk), 那么我們在讀取時就不會出現亂碼. 如下代碼
實操代碼
# 【示例】通過指定文件編碼解決中文亂碼問題 f = open(r"d:\bb.txt", "w", encoding="utf-8") f.write("一個有溫情的小站\n時間靜止不是簡史") f.close()控制臺輸出時
問題描述
我們一般習慣把pycharm所有字符編碼設置成utf-8時. 在我們進行網絡請求時, 有時候會返回亂碼問題, 如下圖
問題分析
因為我們在 pycharm 設置所有字符編碼均為 UTF-8, 但是通過網絡請求得到GBK格式的文本, 然后我們仍以 UTF-8 編碼去解碼就會出現亂碼
解決方案
可以將項目編碼設置成GBK格式即可; 也可以通過文本操作代碼對得到的數據進行GBK格式讀取
亦或者在寫入時, 直接將編碼聲明為UTF-8
write()/writelines()寫入數據
- write(a) :把字符串 a 寫入到文件中
- writelines(b) :把字符串列表寫入文件中,不添加換行符
實操代碼
# 【操作】添加字符串列表數據到文件中 f = open(r"d:\bb.txt", 'w', encoding="utf-8") s = ["什么鬼\n"] * 3 # 通過 \n實現手動換行 f.writelines(s) f.close()close()關閉文件流
由于文件底層是由操作系統控制,所以我們打開的文件對象必須顯式調用 close() 方法關閉文件對象.
當調用 close() 方法時,首先會把緩沖區數據寫入文件(也可以直接調用 flush() 方法),再關閉文件,釋放文件對象
注意:
- close()一般結合異常機制的 finally 一起使用
- 也可以通過 with 關鍵字實現無論何種情況都能關閉打開的文件對象(推薦)
實操代碼
# 【操作】結合異常機制的 finally ,確保關閉文件對象 # "a" 設置打開方式為追加模式 try:f = open(r"d:\c.txt", "a")s = "來自深淵"f.write(s) except BaseException as e:print(e) finally:f.close()with語句(上下文管理器)
with關鍵字 (上下文管理器)可以自動管理上下文資源,不論什么原因跳出 with塊 ,都能確保文件正確的關閉,
并且可以在代碼塊執行完畢后自動還原進入該代碼塊時的現場
實操代碼
# 【操作】使用 with 管理文件寫入操作 s = ["齊格飛"] * 3 with open(r"d:\cc.txt", "w") as f:f.writelines(s)3. 文件的讀取
文件讀取的步驟:
- 打開文本文件對象
- 寫入數據
文件的讀取一般使用如下三個方法:
-
read([size]): 從文件中讀取 size 個字符,并作為結果返回
如果沒有 size 參數,則讀取整個文件. 讀取到文件末尾,會返回空字符串 -
readline(): 讀取一行內容作為結果返回
讀取到文件末尾,會返回空字符串 -
readlines() : 文本文件中,每一行作為一個字符串存入列表中,返回該列表
代碼格式
with open(r"d:\a.txt", "r"[, encoding="utf-8"]) as f:f.read(4)注意:
- 在讀取文件時, 需要注意讀寫時字符編碼的一致性, 如果寫的時候沒有指定編碼(默認GBK), 則在讀取的時候也不需要指定編碼
- 但如果讀的時候未指定編碼, 寫的時候指定, 則會報錯.
例如: 寫的時候指定 encoding="utf-8",
則控制臺報 UnicodeDecodeError: 'utf-8' codec can't decode byte 0xbc in position 13: invalid start byte
實操代碼
# 【操作】 讀取一個文件前4個字符 import picklewith open(r"d:\a.txt", "r") as f:print(f.read(4))# 【操作】文件較小,一次將文件內容讀入到程序中 with open(r"d:\aa.txt", "r") as f:print(f.read())# 【操作】按行讀取一個文件 with open(r"d:\b.txt") as f:while True:lines = f.readline()if not lines: # 在python 中 if not 會將后面對象隱式轉成True或者False進行判斷, 因此遇到空字符串也返回Falsebreakelse:print(lines, end="")print()# 【操作】使用迭代器(每次返回一行)讀取文本文件 # 寫和讀的編碼要對應 with open(r"d:\bb.txt", "r", encoding="utf-8") as f:for a in f:print(a, end="")# 【操作】為文本文件每一行的末尾增加行號 with open(r"d:\c.txt", "r") as f:lines = f.readlines()lines2 = [line.rstrip() + " # " + str(index) + "\n" for index, line in zip(range(1, len(lines) + 1), lines)]with open(r"d:\c.txt", "w") as ff:ff.writelines(lines2)二進制文件的讀取和寫入
二進制文件的處理流程和文本文件流程一致。首先還是要創建文件對象,
創建好二進制文件對象后,仍然可以使用 write() 、 read() 實現文件的讀寫操作
在創建文件對象時, 首先需要指定二進制模式,然后才能創建出二進制文件對象. 例如
- f = open(r"d:\a.txt", 'wb') 可寫的、重寫模式的二進制文件對象
- f = open(r"d:\a.txt", 'ab') 可寫的、追加模式的二進制文件對象
- f = open(r"d:\a.txt", 'rb') 可讀的二進制文件對象
實操代碼
# 二進制文件的讀取和寫入(此操作相當于復制) # f = open(r"d:\a.txt", 'wb') #可寫的、重寫模式的二進制文件對象 # f = open(r"d:\a.txt", 'ab') #可寫的、追加模式的二進制文件對象 # f = open(r"d:\a.txt", 'rb') #可讀的二進制文件對象 with open(r"d:\aaa.png", "rb") as scrFile, open(r"d:\bbb.png", "wb") as destFile:for l in scrFile:destFile.write(l)4. 文件對象的常用屬性和方法
文件對象的屬性
文件對象的打開模式
文件對象的常用方法
文件任意位置操作
利用 seek() 可以將讀取文件的指針移動到指定字節位置上
一個中文字符站兩個字節, 而英文只占一個字節
實操代碼
print("=================文件任意位置操作======================") # 【示例】 seek() 移動文件指針示例 with open(r"d:\cc.txt", "r") as f:print("文件名是{0}".format(f.name)) # 文件名是d:\cc.txtprint(f.tell()) # 0print("讀取文件的內容", str(f.readline())) # 讀取文件的內容 齊格飛齊格飛齊格飛print(f.tell()) # 18f.seek(4, 0) # 中文占2個字節, 因此在seek時需要是2的倍數print("文件讀取的內容", str(f.readline())) # 文件讀取的內容 飛齊格飛齊格飛print(f.tell()) # 18三、文件操作拓展模塊
1. pickle序列化模塊
序列化指的是:將對象轉化成“串行化”數據形式,存儲到硬盤或通過網絡傳輸到其他地方.
反序列化是指相反的過程,將讀取到的“串行化數據”轉化成對象
可以使用pickle模塊中的函數,實現序列化和反序列操作
序列化我們使用:
- pickle.dump(obj, file) obj 就是要被序列化的對象, file 指的是存儲的文件
- pickle.load(file) 從 file 讀取數據,反序列化成對象
實操代碼
import pickle print("=================使用pickle序列化=======================") # 【操作】將對象序列化到文件中 with open("student.info", "wb") as f:name = "時間靜止"age = 18score = [90, 80, 70]resume = {"name": name, "age": age, "score": score}pickle.dump(resume, f)# 【操作】將獲得的數據反序列化成對象 with open("student.info", "rb") as f:resume = pickle.load(f)print(resume)2. csv文件的操作
csv是逗號分隔符文本格式,常用于數據交換、Excel文件和數據庫數據的導入和導出
與Excel文件不同,CSV文件中:
- 值沒有類型,所有值都是字符串
- 不能指定字體顏色等樣式
- 不能指定單元格的寬高,不能合并單元格
- 沒有多個工作表
- 不能嵌入圖像圖表
Python標準庫的模塊csv提供了讀取和寫入csv格式文件的對象
我們在excel中建立一個簡單的表格并且另存為 csv(逗號分隔) ,我們打開查看這個csv文件內容
csv文件讀取
實操代碼
import csvwith open(r"d:\workBook.csv") as a:o_csv = csv.reader(a) # #創建csv對象,它是一個包含所有數據的列表,每一行為一個元素headers = next(o_csv) # #獲得列表對象,包含標題行的信息print(headers)for row in o_csv: # 循環打印各行內容print(row)結果展示
csv文件寫入
實操代碼
# 【操作】 csv.writer 對象寫一個csv文件 headers = ['姓名', '年齡', '工作', '住址'] rows = [('JOJO', '18', '按摩師', '英國'), ('迪奧', '19', '老板', '埃及'), ('喬魯諾喬巴納', '20', '混混', '意呆利')] with open(r"d:\workBook3.csv", "w") as b:b_scv = csv.writer(b) # 創建csv對象b_scv.writerow(headers) # 寫入一行(標題)b_scv.writerows(rows) # 寫入多行(數據)結果展示
3. os和os.path模塊
os模塊 可以幫助我們直接對操作系統進行操作.
我們可以直接調用操作系統的可執行文件、命令,直接操作文件、目錄等等
os模塊 是做系統運維非常重要的基礎
os模塊-調用操作系統命令
實操代碼
# 【示例】 os.system 調用windows系統的記事本程序 os.system("notepad.exe")# 【示例】 os.system 調用windows系統中ping命令 # 如果出現亂碼, 請看 文件操作->文件的寫入->中文亂碼->控制臺輸出時 進行配置 os.system("ping www.baidu.com")# 【示例】運行安裝好的微信 os.startfile(r"C:\Program Files (x86)\Tencent\WeChat\WeChat.exe")os模塊-文件和目錄操作
可以通過前面講的文件對象實現對于文件內容的讀寫操作.
如果還需要對文件和目錄做其他操作,可以使用 os 和 os.path 模塊.
- os 模塊下常用操作文件的方法
- os 模塊下關于目錄操作的相關方法
實操代碼
import os # 【示例】 os 模塊:創建、刪除目錄、獲取文件信息等 print("系統名稱:", os.name) # windows-->nt linux-->posix print("當前操作系統所使用的路徑分隔符:", os.sep) # windows-->\ linux-->/ print("行間隔符:", repr(os.linesep)) # windows-->\r\n linux-->\n print("當前目錄:", os.curdir)a = "3" print(a) # 返回對象的規范字符串表示 print(repr(a)) # 獲取文件和文件夾的相關信息 print(os.stat("MyPy08-FileRead.py"))# 工作目錄的操作 print(os.getcwd()) # 獲取當前工作目錄 os.chdir("D:") # 切換當前工作目錄 os.mkdir("學習資料大全") # 創建目錄 os.rmdir("學習資料大全") # 刪除目錄 # os.makedirs("人種/黃種人/中國人") # 創建多級目錄, 調用成功一次之后, 再次調用會報錯 # os.rename("人種", "亞洲人") # 此方法也只能調用一次 print(os.listdir("亞洲人")) # 當前目錄下的子目錄注意事項
在調用 os.rename() 時, 如果出現報錯 PermissionError: [WinError 5] 拒絕訪問,
則需要你在需要重命名的文件夾上面配置用戶的權限. 修改之后便可進行重命名. 如下圖所示
os.path模塊
os.path 模塊提供了目錄相關(路徑判斷、路徑切分、路徑連接、文件夾遍歷)的操作
實操代碼
列出指定目錄下所有的 .py 文件,并輸出文件名
# 列出指定目錄下所有的 .py 文件,并輸出文件名 import ospath = os.getcwd() file_list = os.listdir(path)for filename in file_list:pos = filename.rfind(".")if filename[pos + 1:] == "py":print(filename, end="\t") print()walk()遞歸遍歷所有文件和目錄
os.walk() 方法是一個簡單易用的文件、目錄遍歷器,可以幫助我們高效的處理文件、目錄方面的事情
格式如下: os.walk(top[, topdown=True[, onerror=None[, followlinks=False]]])
- top :是要遍歷的目錄。 topdown :可選, True ,先遍歷 top 目錄再遍歷子目錄
- 返回三元組( root 、 dirs 、 files ):
root :當前正在遍歷的文件夾本身
dirs :一個列表,該文件夾中所有的目錄的名字
files :一個列表,該文件夾中所有的文件的名字
實操代碼
# 【示例】使用 walk() 遞歸遍歷所有文件和目錄 path = os.getcwd()[:os.getcwd().rfind("\\")] # 獲取上級路徑, 作用是能夠輸出更多的文件 file_list = os.walk(path, topdown=False)for root, dirs, files in file_list:for name in files:print(os.path.join(root, name))for name in dirs:print(os.path.join(root, name)) # 用于拼接目錄輸出結果
遞歸遍歷目錄下所有文件
實操代碼
# 【示例】使用遞歸算法遍歷目錄下所有文件 def my_print_file(path, level):child_files = os.listdir(path)for file in child_files:file_path = os.path.join(path, file)print("\t" * level + file_path[file_path.rfind(os.sep)+1:])if os.path.isdir(file_path):my_print_file(file_path, level + 1)my_print_file(path, 0)4. shutil模塊(拷貝和壓縮)
shutil 模塊是python標準庫中提供的,主要用來做文件和文件夾的拷貝、移動、刪除等;
還可以做文件和文件夾的壓縮、解壓縮操作. os 模塊提供了對目錄或文件的一般操作.
shutil 模塊作為補充,提供了移動、復制、壓縮、解壓等操作,這些 os 模塊都沒有提供
實操代碼-拷貝
import shutil # 【示例】實現文件的拷貝 os.chdir("D:") # 切換當前工作目錄 shutil.copyfile("a.txt", "a_copy.txt")# 【示例】實現遞歸的拷貝文件夾內容(使用 shutil 模塊) shutil.copytree("亞洲人/黃種人", "人種", ignore=shutil.ignore_patterns("*.html", "*htm")) # "音樂"文件夾不存在才能用實操代碼-壓縮與解壓
# 【示例】實現將文件夾所有內容壓縮(使用 shutil 模塊) # 將"亞洲人/黃種人"文件夾下所有內容壓縮到"生物資料"文件夾下生成race.zip shutil.make_archive("生物資料/race", "zip", "亞洲人/黃種人")# 壓縮:將指定的多個文件壓縮到一個zip文件 z = zipfile.ZipFile("a.zip", "w") z.write("a.txt") z.write("b.txt") z.close()# 【示例】實現將壓縮包解壓縮到指定文件夾(使用 shutil 模塊) z2 = zipfile.ZipFile("a.zip", "r") z2.extractall("d:/生物資料") z2.close()總結
以上是生活随笔為你收集整理的Python升级之路( Lv9 ) 文件操作的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: l3gd20陀螺仪精度_L3GD20H陀
- 下一篇: 用Python下载Lofter上“喜欢”