10 - Python文件編程和異常

文件和異常

在實際開發中,常常需要對程序中的數據進行持久化操作,而實現數據持久化最直接簡單的方式就是將數據保存到文件中。說到“文件”這個詞,可能需要先科普一下關于文件系統的知識,對于這個概念,維基百科上給出了很好的詮釋,這里不再浪費筆墨。

在Python中實現文件的讀寫操作其實非常簡單,通過Python內置的open函數,我們可以指定文件名、操作模式、編碼信息等來獲得操作文件的對象,接下來就可以對文件進行讀寫操作了。這里所說的操作模式是指要打開什么樣的文件(字符文件還是二進制文件)以及做什么樣的操作(讀、寫還是追加),具體的如下表所示。

操作模式具體含義
'r'讀取 (默認)
'w'寫入(會先截斷之前的內容)
'x'寫入,如果文件已經存在會產生異常
'a'追加,將內容寫入到已有文件的末尾
'b'二進制模式
't'文本模式(默認)
'+'更新(既可以讀又可以寫)

下面這張圖來自于菜鳥教程網站,它展示了如果根據應用程序的需要來設置操作模式。

在這里插入圖片描述

讀寫文本文件

讀取文本文件時,需要在使用open函數時指定好帶路徑的文件名(可以使用相對路徑或絕對路徑)并將文件模式設置為'r'(如果不指定,默認值也是'r'),然后通過encoding參數指定編碼(如果不指定,默認值是None,那么在讀取文件時使用的是操作系統默認的編碼),如果不能保證保存文件時使用的編碼方式與encoding參數指定的編碼方式是一致的,那么就可能因無法解碼字符而導致讀取失敗。下面的例子演示了如何讀取一個純文本文件。

def main():f = open('致橡樹.txt', 'r', encoding='utf-8')print(f.read())f.close()if __name__ == '__main__':main()

請注意上面的代碼,如果open函數指定的文件并不存在或者無法打開,那么將引發異常狀況導致程序崩潰。為了讓代碼有一定的健壯性和容錯性,我們可以使用Python的異常機制對可能在運行時發生狀況的代碼進行適當的處理,如下所示。

def main():f = Nonetry:f = open('致橡樹.txt', 'r', encoding='utf-8')print(f.read())except FileNotFoundError:print('無法打開指定的文件!')except LookupError:print('指定了未知的編碼!')except UnicodeDecodeError:print('讀取文件時解碼錯誤!')finally:if f:f.close()if __name__ == '__main__':main()

在Python中,我們可以將那些在運行時可能會出現狀況的代碼放在try代碼塊中,在try代碼塊的后面可以跟上一個或多個except來捕獲可能出現的異常狀況。例如在上面讀取文件的過程中,文件找不到會引發FileNotFoundError,指定了未知的編碼會引發LookupError,而如果讀取文件時無法按指定方式解碼會引發UnicodeDecodeError,我們在try后面跟上了三個except分別處理這三種不同的異常狀況。最后我們使用finally代碼塊來關閉打開的文件,釋放掉程序中獲取的外部資源,由于finally塊的代碼不論程序正常還是異常都會執行到(甚至是調用了sys模塊的exit函數退出Python環境,finally塊都會被執行,因為exit函數實質上是引發了SystemExit異常),因此我們通常把finally塊稱為“總是執行代碼塊”,它最適合用來做釋放外部資源的操作。如果不愿意在finally代碼塊中關閉文件對象釋放資源,也可以使用上下文語法,通過with關鍵字指定文件對象的上下文環境并在離開上下文環境時自動釋放文件資源,代碼如下所示。

def main():try:with open('致橡樹.txt', 'r', encoding='utf-8') as f:print(f.read())except FileNotFoundError:print('無法打開指定的文件!')except LookupError:print('指定了未知的編碼!')except UnicodeDecodeError:print('讀取文件時解碼錯誤!')if __name__ == '__main__':main()

除了使用文件對象的read方法讀取文件之外,還可以使用for-in循環逐行讀取或者用readlines方法將文件按行讀取到一個列表容器中,代碼如下所示。

import timedef main():# 一次性讀取整個文件內容with open('致橡樹.txt', 'r', encoding='utf-8') as f:print(f.read())# 通過for-in循環逐行讀取with open('致橡樹.txt', mode='r') as f:for line in f:print(line, end='')time.sleep(0.5)print()# 讀取文件按行讀取到列表中with open('致橡樹.txt') as f:lines = f.readlines()print(lines)if __name__ == '__main__':main()

要將文本信息寫入文件文件也非常簡單,在使用open函數時指定好文件名并將文件模式設置為'w'即可。注意如果需要對文件內容進行追加式寫入,應該將模式設置為'a'。如果要寫入的文件不存在會自動創建文件而不是引發異常。下面的例子演示了如何將1-9999直接的素數分別寫入三個文件中(1-99之間的素數保存在a.txt中,100-999之間的素數保存在b.txt中,1000-9999之間的素數保存在c.txt中)。

from math import sqrtdef is_prime(n):"""判斷素數的函數"""assert n > 0for factor in range(2, int(sqrt(n)) + 1):if n % factor == 0:return Falsereturn True if n != 1 else Falsedef main():filenames = ('a.txt', 'b.txt', 'c.txt')fs_list = []try:for filename in filenames:fs_list.append(open(filename, 'w', encoding='utf-8'))for number in range(1, 10000):if is_prime(number):if number < 100:fs_list[0].write(str(number) + '\n')elif number < 1000:fs_list[1].write(str(number) + '\n')else:fs_list[2].write(str(number) + '\n')except IOError as ex:print(ex)print('寫文件時發生錯誤!')finally:for fs in fs_list:fs.close()print('操作完成!')if __name__ == '__main__':main()

讀寫二進制文件

知道了如何讀寫文本文件要讀寫二進制文件也就很簡單了,下面的代碼實現了復制圖片文件的功能。

def main():try:with open('guido.jpg', 'rb') as fs1:data = fs1.read()print(type(data))  # <class 'bytes'>with open('吉多.jpg', 'wb') as fs2:fs2.write(data)except FileNotFoundError as e:print('指定的文件無法打開.')except IOError as e:print('讀寫文件時出現錯誤.')print('程序執行結束.')if __name__ == '__main__':main()

讀寫JSON文件

通過上面的講解,我們已經知道如何將文本數據和二進制數據保存到文件中,那么這里還有一個問題,如果希望把一個列表或者一個字典中的數據保存到文件中又該怎么做呢?答案是將數據以JSON格式進行保存。JSON是“JavaScript Object Notation”的縮寫,它本來是JavaScript語言中創建對象的一種字面量語法,現在已經被廣泛的應用于跨平臺跨語言的數據交換,原因很簡單,因為JSON也是純文本,任何系統任何編程語言處理純文本都是沒有問題的。目前JSON基本上已經取代了XML作為異構系統間交換數據的事實標準。關于JSON的知識,更多的可以參考JSON的官方網站,從這個網站也可以了解到每種語言處理JSON數據格式可以使用的工具或三方庫,下面是一個JSON的簡單例子。

{'name': '駱昊','age': 38,'qq': 957658,'friends': ['王大錘', '白元芳'],'cars': [{'brand': 'BYD', 'max_speed': 180},{'brand': 'Audi', 'max_speed': 280},{'brand': 'Benz', 'max_speed': 320}]
}

可能大家已經注意到了,上面的JSON跟Python中的字典其實是一樣一樣的,事實上JSON的數據類型和Python的數據類型是很容易找到對應關系的,如下面兩張表所示。

JSONPython
objectdict
arraylist
stringstr
number (int / real)int / float
true / falseTrue / False
nullNone
PythonJSON
dictobject
list, tuplearray
strstring
int, float, int- & float-derived Enumsnumber
True / Falsetrue / false
Nonenull

我們使用Python中的json模塊就可以將字典或列表以JSON格式保存到文件中,代碼如下所示。

import jsondef main():mydict = {'name': '駱昊','age': 38,'qq': 957658,'friends': ['王大錘', '白元芳'],'cars': [{'brand': 'BYD', 'max_speed': 180},{'brand': 'Audi', 'max_speed': 280},{'brand': 'Benz', 'max_speed': 320}]}try:with open('data.json', 'w', encoding='utf-8') as fs:json.dump(mydict, fs)except IOError as e:print(e)print('保存數據完成!')if __name__ == '__main__':main()

json模塊主要有四個比較重要的函數,分別是:

  • dump - 將Python對象按照JSON格式序列化到文件中
  • dumps - 將Python對象處理成JSON格式的字符串
  • load - 將文件中的JSON數據反序列化成對象
  • loads - 將字符串的內容反序列化成Python對象

這里出現了兩個概念,一個叫序列化,一個叫反序列化。自由的百科全書維基百科上對這兩個概念是這樣解釋的:“序列化(serialization)在計算機科學的數據處理中,是指將數據結構或對象狀態轉換為可以存儲或傳輸的形式,這樣在需要的時候能夠恢復到原先的狀態,而且通過序列化的數據重新獲取字節時,可以利用這些字節來產生原始對象的副本(拷貝)。與這個過程相反的動作,即從一系列字節中提取數據結構的操作,就是反序列化(deserialization)”。

目前絕大多數網絡數據服務(或稱之為網絡API)都是基于HTTP協議提供JSON格式的數據,關于HTTP協議的相關知識,可以看看阮一峰老師的《HTTP協議入門》,如果想了解國內的網絡數據服務,可以看看聚合數據和阿凡達數據等網站,國外的可以看看{API}Search網站。下面的例子演示了如何使用requests模塊(封裝得足夠好的第三方網絡訪問模塊)訪問網絡API獲取國內新聞,如何通過json模塊解析JSON數據并顯示新聞標題,這個例子使用了天行數據提供的國內新聞數據接口,其中的APIKey需要自己到該網站申請。

import requests
import jsondef main():resp = requests.get('http://api.tianapi.com/guonei/?key=APIKey&num=10')data_model = json.loads(resp.text)for news in data_model['newslist']:print(news['title'])if __name__ == '__main__':main()

在Python中要實現序列化和反序列化除了使用json模塊之外,還可以使用pickle和shelve模塊,但是這兩個模塊是使用特有的序列化協議來序列化數據,因此序列化后的數據只能被Python識別。關于這兩個模塊的相關知識可以自己看看網絡上的資料。另外,如果要了解更多的關于Python異常機制的知識,可以看看segmentfault上面的文章《總結:Python中的異常處理》,這篇文章不僅介紹了Python中異常機制的使用,還總結了一系列的最佳實踐,很值得一讀。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/39736.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/39736.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/39736.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【CSharp】在class中申明public const int常量的應用

【CSharp】在class中申明public const int常量的應用 1.背景2.代碼3.運行1.背景 常量本身是靜態的,即常量屬于class本身與其實例化對象無關,且常量不可更改。 以上兩種特性在許多應用場景中都有其優勢和應用場合。 1.在定義定義固定值的場景,例如狀態碼、事件類型、配置參…

亞馬遜云科技AWS免費大熱AI應用開發證書(含題庫、開卷)

亞馬遜云科技AWS官方生成式AI免費證書來了&#xff01;內含免費AI基礎課程&#xff01;快速掌握AWS的前沿AI技術&#xff0c;后端開發程序員也可以速成AI專家&#xff0c;了解當下最&#x1f525;的AWS AI架構解決方案&#xff01; 本證書內容包括AWS上的AI基礎知識&#xff0c…

解析Kotlin中的Unit【筆記摘要】

1. Kotlin的Unit 和 Java的void 的區別 // Java public void sayHello() {System.out.println("Hello!") }// Kotlin fun sayHello(): Unit {println("Hello!") }Unit 和 Java 的 void 真正的區別在于&#xff0c;void 是真的表示什么都不返回&#xff0c…

剖析DeFi交易產品之UniswapV4:Swap

文章首發于公眾號&#xff1a;Keegan小鋼 Swap 可分為兩種場景&#xff1a;單池交易和跨池交易。在 PoolManager 合約里&#xff0c;要完成交易流程&#xff0c;會涉及到 lock()、swap()、settle()、take() 四個函數。單池交易時只需要調一次 swap() 函數&#xff0c;而跨池交易…

【面向就業的Linux基礎】從入門到熟練,探索Linux的秘密(七)-shell語法(5)

shell語法的一些知識和練習&#xff0c;可以當作筆記收藏一下&#xff01;&#xff01; 文章目錄 前言 一、shell 二、shell語法 1.文件重定向 2.引入外部腳本 3.作業 總結 前言 shell語法的一些知識和練習&#xff0c;可以當作筆記收藏一下&#xff01;&#xff01; 提示&…

七種大模型微調方法:讓你的Offer拿到爽

在當今的人工智能和機器學習領域&#xff0c;大型預訓練模型&#xff08;如GPT、BERT等&#xff09;已成為解決自然語言處理&#xff08;NLP&#xff09;任務的強大工具。然而&#xff0c;要讓這些模型更好地適應特定任務或領域&#xff0c;往往需要進行微調。本文將詳細介紹七…

手把手教你:如何在51建模網免費下載3D模型?

作為國內領先的3D互動展示平臺&#xff0c;51建模網不僅匯聚了龐大的3D模型資源庫&#xff0c;供用戶免費下載&#xff0c;更集成了在線編輯、格式轉換、內嵌展示及互動體驗等一站式功能&#xff0c;為3D創作者及愛好者搭建起夢想與現實的橋梁。 如何在51建模網免費下載3D模型…

鴻蒙認證值得考嗎?

鴻蒙認證值得考嗎&#xff1f; 鴻蒙認證&#xff08;HarmonyOS Certification&#xff09;是華為為了培養和認證開發者在鴻蒙操作系統&#xff08;HarmonyOS&#xff09;領域的專業技能而設立的一系列認證項目。這些認證旨在幫助開發者和企業工程師提升在鴻蒙生態中的專業技能…

linux——IPC 進程間通信

IPC 進程間通信 interprocess communicate IPC&#xff08;Inter-Process Communication&#xff09;&#xff0c;即進程間通信&#xff0c;其產生的原因主要可以歸納為以下幾點&#xff1a; 進程空間的獨立性 資源隔離&#xff1a;在現代操作系統中&#xff0c;每個進程都…

圖解 Kafka 架構

寫在前面 Kafka 是一個可橫向擴展&#xff0c;高可靠的實時消息中間件&#xff0c;常用于服務解耦、流量削峰。 好像是 LinkedIn 團隊開發的&#xff0c;后面捐贈給apache基金會了。 kafka 總體架構圖 Producer&#xff1a;生產者&#xff0c;消息的產生者&#xff0c;是消息的…

【高考志愿】測繪科學與技術

目錄 一、專業介紹 1.1 專業概述 1.2 專業方向 1.3 課程內容 二、就業前景 三、報考注意事項 四、測繪科學與技術專業排名 五、職業規劃與未來發展 高考志愿選擇測繪科學與技術專業&#xff0c;對于許多有志于空間信息技術領域發展的學生來說&#xff0c;無疑是一個極具…

怎么把錄音轉文字?推薦幾個簡單易操作的方法

在小暑這個節氣里&#xff0c;炎熱的天氣讓人分外渴望效率up&#xff01;Up&#xff01;Up&#xff01; 對于那些在會議或課堂中急需記錄信息的朋友們&#xff0c;手寫筆記的速度往往難以跟上講話的節奏。此時&#xff0c;電腦錄音轉文字軟件就像一陣及時雨&#xff0c;讓記錄…

PHP pwn 學習 (1)

文章目錄 A. PHP extensions for C1. 運行環境與工作目錄初始化2. 構建與加載3. 關鍵結構定義PHP_FUNCTIONINTERNAL_FUNCTION_PARAMETERSzend_execute_data等ZEND_PARSE_PARAMETERS_START等zend_parse_arg_stringzend_module_entryzend_function_entry等PHP類相關 原文鏈接&…

Python 作業題1 (猜數字)

題目 你要根據線索猜出一個三位數。游戲會根據你的猜測給出以下提示之一&#xff1a;如果你猜對一位數字但數字位置不對&#xff0c;則會提示“Pico”&#xff1b;如果你同時猜對了一位數字及其位置&#xff0c;則會提示“Fermi”&#xff1b;如果你猜測的數字及其位置都不對&…

Flower花所:穩定運營的數字貨幣交易所

Flower花所是一家穩定運營的數字貨幣交易所&#xff0c;致力于為全球用戶提供安全、高效的數字資產交易服務。作為一家長期穩定運營的數字貨幣交易平臺&#xff0c;Flower花所以其可靠的技術基礎和優質的客戶服務而聞名。 平臺穩定性與可靠性&#xff1a; 持續運營&#xff1a;…

Vue前端練習

此練習項目只涉及前端&#xff0c;主要是vue和ElementUI框架的使用。&#xff08;ElementUI官網&#xff1a;Element - The worlds most popular Vue UI framework&#xff09; 一、環境準備 安裝idea 安裝Node.js 一鍵式安裝(不需要做任何配置) npm -v&#xff08;也可用nod…

mysql-sql-第十五周

學習目標&#xff1a; sql 學習內容&#xff1a; 41.查詢沒有學全所有課程的同學的信息 select *from students where students.stunm not in (select score.stunm from score group by score.stunm having count(score.counm) (select count(counm) from course)) 42.查詢…

數據結構_線性表

線性表的定義和特點 線性表是具有相同特性的數據元素的一個有限序列 :線性起點/起始節點 :的直接前驅 :的直接后繼 :線性終點/終端節點 n:元素總個數,表長 下標:是元素的序號,表示元素在表中的位置 n0時稱為空表 線性表 由n(n>0)個數據元素(結點),組成的有限序列 將…

安卓模擬器如何修改ip地址

最近很多老鐵玩游戲的&#xff0c;想多開模擬器一個窗口一個IP&#xff0c;若模擬器窗口開多了&#xff0c;IP一樣會受到限制&#xff0c;那么怎么更換自己電腦手機模擬器IP地址呢&#xff0c;今天就教大家一個修改模擬器IP地址的方法&#xff01;廢話不多說&#xff0c;直接上…

Matlab 中 fftshift 與 ifftshift

文章目錄 【 1. fftshift、ifftshift 的區別】【 2. fftshift(fft(A)) 作圖 】【 3. fftshift(fft(A)) 還原到 A 】Matlab 直接對信號進行 FFT 的結果中,前半部分是正頻,后半部分是負頻,為了更直觀的表示,需要將 負頻 部分移到 前面。【 1. fftshift、ifftshift 的區別】 M…