###### 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)
```