1. 程式人生 > >【Python】程式設計筆記8

【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))