Python文件和異常


程序和運行時數據是在內存中駐留的,涉及到數據交換的地方,通常是磁盤、網絡等,因此需要IO接口。
IO編程中,Stream(流)是一個很重要的概念,可以把流想象成一個水管,數據就是水管里的水,但是只能單向流動。Input Stream就是數據從外面(磁盤、網絡)流進內存,Output Stream就是數據從內存流到外面去。
CPU和內存的速度遠遠高於外設的速度。

  • 同步IO
  • 異步IO

操作IO的能力都是由操作系統提供的,每一種編程語言都會把操作系統提供的低級C接口封裝起來方便使用。

1. 文件

1.1 讀文件

try:
	f = open(r'C:\Users\84745\Desktop\test.txt', 'r')
	print(f.read())
finally:
	if f:
		f.close() # 關閉文件

由於反斜杠在Python中被視為轉義標記,為在Windows中確保萬無一失,應以原始字符串的方式指定路徑,即在開頭的單引號前加上r
文件使用完畢后必須關閉,因為文件對象會占用操作系統的資源,並且操作系統同一時間能打開的文件數量也是有限的。

Python引入了with語句來自動幫我們調用close()方法。

with open(r'C:\Users\84745\Desktop\test.txt') as f:
	contents = f.read()
	print(contents)
	
# 逐行讀取
filename = 'pi_digits.txt'

with open(filename) as f:
    for line in f:
        print(line)

# 在with代碼塊外訪問文件的內容
filename = 'pi_digits.txt'

with open(filename) as f:
    lines = f.readlines()

for line in lines:
    print(line.rstrip())

3.1415926535
  8979323846
  2643383279

1.2 寫文件

寫文件和讀文件的唯一區別是調用open()函數時,傳入標識符'w'或者'wb'表示寫文本文件或寫二進制文件。
當我們寫文件時,操作系統往往不會立刻把數據寫入磁盤,而是放到內存緩存起來,空閑的時候再慢慢寫入。只有調用close()方法時,操作系統才保證把沒有寫入的數據全部寫入磁盤。忘記調用close()的后果是數據可能只寫了一部分到磁盤,剩下的丟失了。

filename = 'programming.txt'

with open(filename, 'w') as f:
    f.write("I love programming.")

1.3 序列化

我們把變量從內存中變成可存儲或傳輸的過程稱之為序列化
把變量內容從序列化的對象重新讀到內存里稱之為反序列化
Python提供了pickle模塊來實現序列化。

>>> d = dict(name='Bob', age=20, score=88)
>>> f = open('dump.txt', 'wb')
>>> pickle.dump(d, f)
>>> f.close()
>>> f = open('dump.txt', 'rb')
>>> d = pickle.load(f)
>>> f.close()
>>> d
{'name': 'Bob', 'age': 20, 'score': 88}

1.3.1 JSON

如果我們要在不同的編程語言之間傳遞對象,就必須把對象序列化為標准格式,比如XML,但更好的方法是序列化為JSON,因為JSON表示出來就是一個字符串,可以被所有語言讀取,也可以方便地存儲到磁盤或者通過網絡傳輸。
Python內置的json模塊提供了非常完善的Python對象到JSON格式的轉換。

>>> import json
>>> d = dict(name='Bob', age=20, score=88)
>>> json.dumps(d)
'{"name": "Bob", "age": 20, "score": 88}'
>>> json_str = '{"age": 20, "score": 88, "name": "Bob"}'
>>> json.loads(json_str)
{'age': 20, 'score': 88, 'name': 'Bob'}
import json

class Student(object):
    def __init__(self, name, age, score):
        self.name = name
        self.age = age
        self.score = score


def student2dict(std):
    return {
        'name': std.name,
        'age': std.age,
        'score': std.score
    }
	
	
s = Student('Bob', 20, 88)
print(json.dumps(s, default=student2dict))

# {"name": "Bob", "age": 20, "score": 88}

通常class的實例都有一個__dict__屬性,它就是一個字典,用來存儲實例變量。

import json

class Student(object):
    def __init__(self, name, age, score):
        self.name = name
        self.age = age
        self.score = score


s = Student('Bob', 20, 88)
print(json.dumps(s, default=lambda obj: obj.__dict__))

# {"name": "Bob", "age": 20, "score": 88}
# 把JSON反序列化為一個Student對象實例。
import json

class Student(object):
    def __init__(self, name, age, score):
        self.name = name
        self.age = age
        self.score = score


def dict2student(d):
    return Student(d['name'], d['age'], d['score'])

json_str = '{"age": 20, "score": 88, "name": "Bob"}'
print(json.loads(json_str, object_hook=dict2student))

# <__main__.Student object at 0x00BBAA30>

2. 異常

Python使用被稱為異常的特殊對象來管理程序執行期間發生的錯誤。

2.1 處理異常

如果你編寫了處理該異常的代碼,程序將繼續運行;如果你未對異常進行處理,程序將停止,並顯示一個Traceback,其中包含有關異常的報告。
異常是使用try-except代碼塊處理的。

try:
    print(5/0)
except ZeroDivisionError:
    print("You can't divide by zero!")

# You can't divide by zero!

一個try語句可能包含多個except子句,分別來處理不同的特定的異常。最多只有一個分支會被執行。
一個except子句可以同時處理多個異常,這些異常將被放在一個括號里成為一個元組。
最后一個except子句可以忽略異常的名稱,它將被當作通配符使用。你可以使用這種方法打印一個錯誤信息,然后再次把異常拋出。
try-except語句還有一個可選的else子句,如果使用這個子句,那么必須放在所有的except子句之后。這個子句將在try子句沒有發生任何異常的時候執行。

2.2 拋出異常

Python使用raise語句拋出一個指定的異常。
raise唯一的一個參數指定了要被拋出的異常。它必須是一個異常的實例或者是異常的類(即Exception的子類)。


參考資料:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM