【Python】程式設計筆記8
文章目錄
IO程式設計
通常,程式完成 IO 操作會有 Input 和 Output 兩個資料流。Input Stream 就是資料從外面(磁碟、網路)流進記憶體, Output Stream 就是資料從記憶體流到外面去。
分類:同步IO、非同步IO。區別就在於是否等待 IO 執行的結果。
非同步 IO 來編寫程式效能會遠遠高於同步 IO,但是非同步 IO
的缺點是程式設計模型複雜。
一、檔案讀寫
讀寫檔案:請求作業系統開啟一個檔案物件(通常稱為檔案描述符),然後,通過作業系統提供的介面從這個檔案物件中讀取資料(讀檔案),或者把資料寫入這個檔案物件(寫檔案)。
1、讀檔案
步驟:open()、read()、close()
(1)open()
open() 函式傳入檔名和標示符。其中,r 表示只讀。
f = open('E:\codes\python\basic\1.py', 'r')
==》若檔案不存在,則丟擲 IOError 錯誤。
(2)read()
呼叫 read() 方法可一次讀取檔案的全部內容到記憶體中,用一個 str 物件表示。
f.read()
(3)close()
關閉檔案——close() 方法
==》檔案使用完畢後必須關閉,因為檔案物件會佔用作業系統的資源,並且作業系統同一時間能開啟的檔案數量也是有限的。
f.close()
(4)try…finally實現
避免產生IOError的錯誤,而導致後面close()無法呼叫。
try:
f = open('E:\\codes\\python\\basic\\1.txt', 'r')
print(f.read())
finally:
if f:
f.close()
(5)with 語句(強烈推薦)
簡潔、不用 f.close() 方法
with open('E:\\codes\\python\\basic\\1.txt', 'r') as f:
print(f.read())
(6)注意
- 若檔案大,直接呼叫 read() 會導致記憶體爆掉==》read(size)方法,每次最多讀取 size 個位元組的內容;
- readline() 函式:每次讀取一行內容;
- readlines() 函式:一次讀取所有內容並按行返回 list;
(7)二進位制檔案
二進位制檔案:圖片、視訊等等==》‘rb’模式開啟檔案
f = open('/Users/michael/test.jpg', 'rb')
f.read()
# b'\xff\xd8\xff\xe1\x00\x18Exif\x00\x00...' # 十六進位制表示的位元組
(8)字元編碼——encoding、errors
讀取 GBK 編碼的檔案。==》encoding = ‘gbk’
當遇到 UnicodeDecodeError (檔案中夾雜一些非法編碼的字元)==》errors = ‘ignore’,也就是忽略編碼錯誤。
f = open('/Users/michael/gbk.txt', 'r', encoding='gbk', errors='ignore')
2、寫檔案
(1)基本
open() 函式,標示符為 ‘w’ 或 ‘wb’,表示寫文字檔案或寫二進位制檔案。
f = open('/Users/michael/test.txt', 'w')
f.write('Hello, world!')
f.close()
注意:寫檔案時,作業系統往往不會立刻把資料寫入磁碟,而是放到記憶體快取起來,空閒的時候再慢慢寫入。只有呼叫 close()方法時,作業系統才保證把沒有寫入的資料全部寫入磁碟。
(2)with 語句
可以使用 encoding 引數設定指定的編碼。
with open('/Users/michael/test.txt', 'w') as f:
f.write('Hello, world!')
二、StringIO 和 BytesIO
1、StringIO
表示在記憶體中讀寫 str。
from io import StringIO
#### 寫入
f = StringIO()
print(f.write('hello'))
print(f.write(' '))
print(f.write('world!'))
# getvalue(): 獲得寫入後的 str
print(f.getvalue())
#### 讀取
f = StringIO('Hello!\nHi!\nGoodbye!')
while True:
s = f.readline()
if s == '':
break
print(s.strip())
輸出結果
5
1
6
hello world!
Hello!
Hi!
Goodbye!
2、BytesIO
表示在記憶體中讀寫 二進位制資料。
from io import BytesIO
### 寫入
f = BytesIO()
print(f.write('中文'.encode('utf-8')))
print(f.getvalue())
### 讀取
f = BytesIO(b'\xe4\xb8\xad\xe6\x96\x87')
print(f.read())
輸出結果
6
b'\xe4\xb8\xad\xe6\x96\x87'
b'\xe4\xb8\xad\xe6\x96\x87'
三、操作檔案和目錄
模組:os
注意:os 模組的某些函式是跟作業系統相關的
1、系統屬性資訊
import os
print(os.name) # 作業系統型別
# uname()在 Linux 有,Windows 沒有
# print(os.uname()) # 獲取詳細的系統資訊
print(os.environ) # 環境變數
print(os.environ.get('PATH')) # 獲取某個環境變數的值
2、操作檔案和目錄
在 os 模組 和 os.path 模組中 + shutil 模組
print(os.path.abspath('.')) # 檢視當前目錄的絕對路徑
# 在某個目錄下建立一個新目錄,首先把新目錄的完整路徑表示出來
print(os.path.join('E:\codes\python\\basic', 'testdir'))
## 建立一個目錄
os.mkdir('E:\codes\python\\basic\\1')
## 刪除一個目錄
os.rmdir('E:\codes\python\\basic\\1')
# 對檔案重新命名:
os.rename('test.txt', 'test.py')
# 刪掉檔案:
os.remove('test.py')
# 複製檔案
from shutil import copyfile
copyfile('1.py', '11.py') # 原始檔 ==》 目標檔案
把兩個路徑合成一個時,不要直接拼字串。==》os.path.join() 函式,可以正確處理不同作業系統的路徑分隔符。
同理,要拆分路徑時==》os.path.split()函式,後一級別總是目錄或檔名。
拆分副檔名——os.path.splitext() 函式
過濾檔案
## 列出所有的.py 檔案
print([x for x in os.listdir('.') if os.path.isfile(x) and os.path.splitext(x)[1] == '.py'])
四、序列化
序列化:把變數從記憶體中變成可儲存或傳輸的過程。在Python中稱為 picking。
反序列化:把變數內容從序列化的物件重新讀到記憶體裡的過程。在Python中稱為 unpicking。
1、pickle模組
把一個物件序列化並寫入檔案。
import pickle
d = dict(name = 'Bob', age = 20, score = 88)
pickle.dumps(d)
# b'\x80\x03}q\x00(X\x04\x00\x00\x00nameq\x01X\x03\x00\x00\x00Bobq\x02X\x03\x00\x00\x00ageq\x03K\x14X\x05\x00\x00\x00scoreq\x04KXu.'
## 序列化到dump.txt檔案中
f = open('dump.txt', 'wb')
pickle.dump(d, f)
f.close()
## 反序列化
f = open('dump.txt', 'rb')
d = pickle.load(f)
f.close()
print(d)
pickle.dumps() 方法:把任意物件序列化成一個bytes,然後就可以把這個 bytes 寫入檔案。
pickle.dump() 方法:直接把物件序列化後寫入一個 file-like Object.
把物件從磁碟讀取到記憶體時。
(1)內容=》bytes=》pickle.loads() 方法反序列化出物件
(2)直接用 pickle.load() 從一個file-like Object 中直接反序列化出物件。
注意:Python不同版本的Pickle可能不相容,所以只能儲存那些不重要的資料,不能成功反序列化也沒關係。
2、JSON模組
序列化的標準化格式:JSON,且比XML快,可以在Web網頁中讀取。
JSON 與 Python的內建資料型別對應如下:
JSON型別 | Python型別 |
---|---|
{} | dict |
[] | list |
“string” | str |
1234.56 | int 或 float |
true/false | True/False |
null | None |
dict 《==》dict
import json
d = dict(name = 'Bob', age = 20, score = 88)
print(json.dumps(d))
json_str = '{"age":20, "score":88, "name":"Bob"}'
print(json.loads(json_str))
(1)class 的序列化
import json
class Student(object):
def __init__(self, name, age, score):
self.name = name
self.age = age
self.score = score
## 序列化——default引數
s = Student('Bob', 20, 88)
# obj.__dict__:把任意 class 的例項變為 dict
print(json.dumps(s, default=lambda obj: obj.__dict__))
## 反序列化
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))