###### tags: `python` # pickle ## Pickle定義 **物件序列化:**直接保存物件狀態,在下次重新執行程式時讀取以恢復運算時必要的資料 - 檔案可能會比原本純文字版本更大 - 產生Pickle File的精神是直接物件交換到另一個Python Program,繼續做後續運算,並且載入時間縮短 ## 將資料存成pickle格式的檔案 ```python= import pickle # 注意:使用 pickle 的時候,檔名不可以命名成 pickle.py a = [1,3,5,7,9] d = {'cat':1000, 2:['1','a','XX',3], '3':{'k':'tao', 6:10}} s = 'my name' # 存資料 with open('my_file.pickle','wb') as file: pickle.dump(a, file) # 使用 dump 把 data 倒進去 file 裡面 pickle.dump(d, file) pickle.dump(s, file) ``` ## 讀取pickle格式的檔案 ```python= import pickle # 注意:使用 pickle 的時候,檔名不可以命名成 pickle.py # 拿資料 with open('my_file.pickle','rb') as file1: print(file1) a = pickle.load(file1) # 逐行拿資料,包括可以拿到 data type d = pickle.load(file1) s = pickle.load(file1) print(a) print(d) print(s) ``` ## 實務範例 ```python= import pickle class DVD: def __init__(self, title, year=None, duration=None, director_id=None): self.title = title self.year = year self.duration = duration self.director_id = director_id self.filename = self.title.replace(' ', '_') + '.pickle' def check_filename(self, filename): if filename is not None: self.filename = filename def save(self, filename=None): self.check_filename(filename) fh = None try: data = (self.title, self.year, self.duration, self.director_id) fh = open(self.filename, 'wb') pickle.dump(data, fh) except (EnvironmentError, pickle.PicklingError) as err: print(str(err)) raise SaveError(str(err)) finally: if fh is not None: fh.close() def load(self, filename=None): self.check_filename(filename) fh = None try: fh = open(self.filename, 'rb') data = pickle.load(fh) (self.title, self.year, self.duration, self.director_id) = data except (EnvironmentError, pickle.PicklingError) as err: raise LoadError(str(err)) finally: if fh is not None: fh.close() # filename = 'PyConTutorial2013.pickle' # dvd1 = DVD('PyCon Tutorial', 2013, 1, 'Justin Lin') # dvd1.save() # dvd2 = DVD('PyCon Tutorial') # dvd2.load() # attrs = vars(dvd2) # 可以把物件內的屬性變成字典型態 # for title, value in attrs.items(): # print(title, ': ', value) filename = 'PyConTutorial2013.pickle' dvd1 = DVD('[工具] 建置自己的同步備份系統 – Nextcloud', 2018, 1, '一介資男') dvd1.save() dvd2 = DVD('[工具] 建置自己的同步備份系統 – Nextcloud') dvd2.load() attrs = vars(dvd2) # 可以把物件內的屬性變成字典型態 for title, value in attrs.items(): print(title, ': ', value) ``` ## 使用csv儲存資料(不使用pickle) ```python= import csv class DVD: def __init__(self, title, year=None, duration=None, director_id=None): self.title = title self.year = year self.duration = duration self.director_id = director_id self.filename = self.title.replace(' ', '_') + '.csv' def check_filename(self, filename): if filename is not None: self.filename = filename def save(self, filename=None): self.check_filename(filename) fh = None try: data = (self.title, self.year, self.duration, self.director_id) fh = open(self.filename, 'w') csvWriter = csv.writer(fh) csvWriter.writerow(data) except Exception as err: raise SaveError(str(err)) finally: if fh is not None: fh.close() def load(self, filename=None): self.check_filename(filename) fh = None try: fh = open(self.filename, 'r') csvReader = csv.reader(fh) csvList = list(csvReader) print(csvList) (self.title, self.year, self.duration, self.director_id) = csvList[0] except Exception as err: raise LoadError(str(err)) finally: if fh is not None: fh.close() filename = 'PyConTutorial2013.pickle' dvd1 = DVD('[工具] 建置自己的同步備份系統 – Nextcloud', 2018, 1, '一介資男') dvd1.save() dvd2 = DVD('[工具] 建置自己的同步備份系統 – Nextcloud') dvd2.load() attrs = vars(dvd2) # 可以把物件內的屬性變成字典型態 for title, value in attrs.items(): print(title, ': ', value) ```