Python 提供了多種序列化工具,讓開發者能將程式中的物件轉換成可儲存或傳輸的格式。瞭解這些工具的特性,才能在專案中做出最佳選擇。本文將探討 JSON、Pickle 和 Shelve,分析它們的優缺點及適用場景。JSON 是一種輕量級的資料交換格式,易於閱讀、編寫,也易於機器解析和生成。它根據 JavaScript 語法,但獨立於程式語言,成為 Web API 和資料儲存的常用格式。Python 的 json 模組提供了方便的 API,用於在 Python 物件和 JSON 字串之間進行轉換。使用時要注意資料的編碼問題,尤其是有非 ASCII 字元時,ensure_ascii=False 可確保中文字元正確顯示。JSON 的優點是易於閱讀和編寫、跨平台、跨語言,與支援度廣泛,缺點是僅支援基本資料型別,無法序列化複雜的 Python 物件,安全性也較低。Pickle 是 Python 內建模組,能將 Python 物件序列化為二進位格式,儲存到檔案中,可以儲存類別、函式,甚至是程式的狀態,非常適合儲存訓練好的機器學習模型。使用 pickle.dump() 序列化物件並寫入檔案,pickle.load() 從檔案讀取並反序列化。Pickle 的優點是可以序列化幾乎所有 Python 物件,使用簡單方便,缺點是二進位格式可讀性差,跨語言相容性差,與存在安全性風險,強烈建議只反序列化信任來源的資料。Shelve 模組建立在 Pickle 之上,提供簡單的鍵值對儲存方式,可將 Python 物件持久化到磁碟,類別似持久化的字典。使用 shelve.open() 開啟 shelve 檔案,像操作字典一樣儲存和讀取資料。Shelve 的優點是使用簡單,方便持久化 Python 物件,缺點是根據 Pickle 存在安全風險,不適合高併發應用,與檔案大小可能隨資料增長而變大。
檔案時間魔法:Python 讀取、轉換與時區處理
在日常開發中,讀取檔案的建立、修改和存取時間是常見的需求。Python 提供了豐富的模組來處理這些時間資訊,讓開發者能夠輕鬆地進行時間戳轉換、時區調整等操作。玄貓將分享如何使用 os、time、datetime 和 pytz 模組,讓檔案時間處理變得更加靈活。
時間戳記:檔案的時光膠囊
檔案的每個動作都會留下時間的痕跡,這些痕跡以時間戳記的形式儲存。時間戳記是一個數值,代表從 epoch(通常是 1970 年 1 月 1 日午夜)到特定時間點的秒數。
Python 的 os 模組提供方法來取得這些時間戳記:
os.path.getctime(file_path): 取得檔案的建立時間。os.path.getmtime(file_path): 取得檔案的最後修改時間。os.path.getatime(file_path): 取得檔案的最後存取時間。
import os
import time
file_path = '/path/to/file.txt'
# 取得檔案建立時間
creation_time = os.path.getctime(file_path)
creation_time = time.localtime(creation_time)
print("建立時間:", time.strftime("%Y-%m-%d %H:%M:%S", creation_time))
# 取得檔案修改時間
modification_time = os.path.getmtime(file_path)
modification_time = time.localtime(modification_time)
print("修改時間:", time.strftime("%Y-%m-%d %H:%M:%S", modification_time))
# 取得檔案存取時間
access_time = os.path.getatime(file_path)
access_time = time.localtime(access_time)
print("存取時間:", time.strftime("%Y-%m-%d %H:%M:%S", access_time))
內容解密
os.path.getctime()、os.path.getmtime()和os.path.getatime()函式分別用於取得檔案的建立、修改和存取時間戳記。time.localtime()函式將時間戳記轉換為本地時間的time結構。time.strftime()函式用於格式化時間結構,將其轉換為易於閱讀的字串。
時間格式轉換:開發客製化時光儀錶板
時間戳記是給機器看的,但人類更喜歡易讀的時間格式。strftime() 函式讓我們可以將時間轉換為各種格式:
import os
import time
file_path = '/path/to/file.txt'
# 取得檔案修改時間
modification_time = os.path.getmtime(file_path)
modification_time = time.localtime(modification_time)
# 轉換為 ISO 格式
modification_time_str = time.strftime("%Y-%m-%d %H:%M:%S", modification_time)
print("修改時間 (ISO):", modification_time_str)
# 轉換為自定義格式
modification_time_str = time.strftime("%b %d, %Y %I:%M:%S %p", modification_time)
print("修改時間 (自定義):", modification_time_str)
內容解密
%Y: 年份(四位數)%m: 月份(01-12)%d: 日期(01-31)%H: 小時(00-23)%M: 分鐘(00-59)%S: 秒數(00-59)%b: 月份簡寫(Jan, Feb, …)%I: 小時(01-12)%p: AM 或 PM
時間間隔計算:timedelta 的妙用
timedelta 類別可以表示時間的長度,讓我們可以進行時間的加減運算。
from datetime import datetime, timedelta
import os
file_path = '/path/to/file.txt'
# 取得檔案修改時間
modification_time = datetime.fromtimestamp(os.path.getmtime(file_path))
# 取得目前時間
current_time = datetime.now()
# 計算時間間隔
time_interval = current_time - modification_time
print("時間間隔:", time_interval)
# 加減時間
new_time = current_time + timedelta(days=1)
print("明天:", new_time)
new_time = current_time - timedelta(hours=1)
print("一小時前:", new_time)
# 格式化時間間隔
time_interval = timedelta(hours=1, minutes=30, seconds=45)
time_interval_str = str(time_interval)
print("時間間隔:", time_interval_str)
內容解密
datetime.fromtimestamp()將時間戳記轉換為datetime物件。datetime.now()取得目前的datetime物件。timedelta(days=1)建立一個表示一天的timedelta物件。str(time_interval)將timedelta物件轉換為字串。
時區轉換:pytz 讓時間無國界
在處理跨時區的檔案時,pytz 是一個強大的工具,可以確保時間轉換的準確性。
from datetime import datetime
import pytz
# 建立一個 datetime 物件,表示原始時區的時間
original_time = datetime(2023, 3, 17, 15, 30)
# 轉換時區
original_timezone = pytz.timezone('America/New_York')
new_timezone = pytz.timezone('Europe/London')
new_time = original_timezone.localize(original_time).astimezone(new_timezone)
print("原始時間:", original_time)
print("轉換後時間:", new_time)
內容解密
pytz.timezone('America/New_York')建立一個表示紐約時區的時區物件。original_timezone.localize(original_time)將原始時間本地化為紐約時區。astimezone(new_timezone)將時間轉換為倫敦時區。
透過 os、time、datetime 和 pytz 模組的靈活運用,玄貓可以輕鬆地讀取、轉換和處理檔案的時間資訊,讓時間在程式中不再是難題。
時間魔法:Python 檔案操作中的時區與資料持久化
在資料處理的世界裡,時間和資料的儲存是兩個不可或缺的要素。Python 提供了強大的工具,如 pytz 和 dateutil 處理時區轉換,以及 json 模組進行資料序列化與持久化。讓玄貓帶領大家深入瞭解如何在檔案操作中運用這些工具,確保時間的精確性和資料的可靠性。
時區處理:pytz 的妙用
時區處理是讓許多開發者頭痛的問題,尤其是在處理跨國資料或需要精確時間戳記的應用中。pytz 模組提供了一個全面的時區資料函式庫,讓時區轉換變得輕鬆可靠。
from datetime import datetime
import pytz
# 建立一個 datetime 物件,表示原始時區的時間
original_time = datetime(2023, 3, 12, 2, 30)
# 設定原始時區和目標時區
original_timezone = pytz.timezone('America/New_York')
new_timezone = pytz.timezone('Europe/London')
# 將 datetime 物件本地化到原始時區,並轉換為目標時區
new_time = original_timezone.localize(original_time, is_dst=None).astimezone(new_timezone)
print("原始時間:", original_time)
print("轉換後時間:", new_time)
內容解密
- 首先,我們匯入了
datetime和pytz模組。 original_time變數儲存了一個datetime物件,代表紐約時間2023-03-12 02:30:00。original_timezone和new_timezone變數分別設定為紐約和倫敦的時區。localize()方法將original_time物件本地化到紐約時區。is_dst=None引數表示讓pytz自動判斷是否為日光節約時間。astimezone()方法將本地化後的datetime物件轉換為倫敦時區。- 最後,我們印出原始時間和轉換後的時間。
pytz 的強大之處在於它能正確處理日光節約時間 (Daylight Saving Time, DST) 的轉換。透過 is_dst=None 引數,pytz 會自動判斷時間是否落在 DST 轉換期間,並進行相應的調整。
更彈性的日期處理:dateutil
除了 pytz,dateutil 也是一個處理日期時間的利器。它提供了更靈活的日期時間字串解析和日期運算功能。
from datetime import datetime
from dateutil.parser import parse
from dateutil.relativedelta import relativedelta
# 解析 ISO 8601 格式的日期字串
date_string = '2023-03-17'
date = parse(date_string)
print("解析後的日期:", date)
# 取得目前時間
now = datetime.now()
# 加上一週
one_week_from_now = now + relativedelta(weeks=1)
print("目前時間:", now)
print("一週後:", one_week_from_now)
內容解密
- 我們匯入了
datetime、parse和relativedelta。 parse()函式將 ISO 8601 格式的日期字串"2023-03-17"解析為datetime物件。datetime.now()取得目前的日期和時間。relativedelta(weeks=1)建立一個表示「一週」的時間差物件。- 將
now加上relativedelta(weeks=1),即可得到一週後的日期和時間。
dateutil 讓日期時間的解析和運算變得更加直觀和方便。無論是處理各種格式的日期字串,還是進行複雜的日期加減,dateutil 都能輕鬆應對。
資料持久化:json 的簡潔之道
資料序列化是將 Python 物件轉換為可儲存或傳輸的格式。json 模組提供了一種簡單與廣泛使用的資料序列化方式。
import json
# 建立一個 Python 字典
person = {"name": "John", "age": 30, "city": "New York"}
# 將字典序列化為 JSON 字串
json_string = json.dumps(person)
print(json_string)
# 將字典序列化為 JSON 並寫入檔案
with open("person.json", "w") as f:
json.dump(person, f)
# 從 JSON 字串反序列化為 Python 物件
person = json.loads(json_string)
print(person)
# 從 JSON 檔案反序列化為 Python 物件
with open("person.json", "r") as f:
person = json.load(f)
print(person)
內容解密
json.dumps()函式將 Python 字典person序列化為 JSON 格式的字串。json.dump()函式將 Python 字典person序列化為 JSON 格式,並寫入名為"person.json"的檔案中。json.loads()函式將 JSON 格式的字串反序列化為 Python 字典。json.load()函式從"person.json"檔案讀取 JSON 格式的資料,並反序列化為 Python 字典。
json 格式簡潔易讀,與被廣泛支援,因此成為資料持久化的理想選擇。透過 json 模組,我們可以輕鬆地將 Python 物件儲存到檔案中,並在需要時讀取出來。
總結來說,pytz、dateutil 和 json 是 Python 檔案操作中不可或缺的工具。它們分別負責處理時區轉換、日期時間解析和資料序列化,讓玄貓在處理時間和資料時更加得心應手。掌握這些工具,能讓你的 Python 程式更加健壯和可靠。
Python資料持久化攻略:JSON、Pickle、Shelve與DBM的深度解析
在資料科學與軟體工程的世界中,如何有效地儲存和讀取資料至關重要。Python提供了多種序列化(Serialization)工具,讓開發者能將程式中的物件轉換為可儲存或傳輸的格式。本文將探討JSON、Pickle、Shelve和DBM這四種常見的序列化方法,分析它們的優缺點及適用場景,助您在專案中做出最佳選擇。
JSON:輕量級資料交換的標準
JSON(JavaScript Object Notation)是一種輕量級的資料交換格式,易於閱讀和編寫,也易於機器解析和生成。它根據JavaScript語法,但獨立於程式語言,成為Web API和資料儲存的常用格式。
玄貓小提示: 在處理JSON資料時,務必注意資料的編碼問題,特別是當資料包含非ASCII字元時。
Python與JSON:json模組的使用
Python的json模組提供了方便的API,用於在Python物件和JSON字串之間進行轉換。
import json
# Python字典
data = {
"name": "玄貓",
"age": 30,
"city": "台北"
}
# 序列化為JSON
json_string = json.dumps(data, ensure_ascii=False) # ensure_ascii=False 處理中文
print(json_string)
# JSON反序列化為Python物件
loaded_data = json.loads(json_string)
print(loaded_data)
內容解密:
json.dumps(): 將Python物件序列化為JSON字串。ensure_ascii=False確保中文字元能正確顯示。json.loads(): 將JSON字串反序列化為Python物件。
JSON的優缺點
- 優點
- 易於閱讀和編寫
- 跨平台、跨語言
- 廣泛的支援度
- 缺點
- 僅支援基本資料型別(字串、數字、布林值、列表、字典)
- 無法序列化複雜的Python物件(例如:類別例項)
- 安全性較低,可能存在注入風險
Pickle:Python物件的完全儲存
pickle是Python內建模組,能將Python物件序列化為二進位格式,並將其儲存到檔案中。這意味著你可以儲存Python的類別、函式,甚至是程式的狀態。
玄貓經驗分享: 在為某個機器學習專案設計資料儲存方案時,我發現pickle非常適合儲存訓練好的模型,因為它可以完整儲存模型的結構和引數。
Pickle的使用範例
import pickle
# 定義一個類別
class Person:
def __init__(self, name, age, city):
self.name = name
self.age = age
self.city = city
def __str__(self):
return f"{self.name} ({self.age}) from {self.city}"
# 建立一個Person物件
person = Person("玄貓", 30, "台北")
# 序列化到檔案
with open("person.pickle", "wb") as f:
pickle.dump(person, f)
# 從檔案反序列化
with open("person.pickle", "rb") as f:
loaded_person = pickle.load(f)
print(loaded_person)
內容解密:
pickle.dump(object, file): 將Python物件序列化並寫入檔案。"wb"表示以二進位寫入模式開啟檔案。pickle.load(file): 從檔案讀取序列化的資料並反序列化為Python物件。"rb"表示以二進位讀取模式開啟檔案。
Pickle的優缺點
- 優點
- 可以序列化幾乎所有的Python物件
- 使用簡單方便
- 缺點
- 二進位格式,可讀性差
- 跨語言相容性差
- 安全性風險高:反序列化惡意
pickle資料可能執行任意程式碼。強烈建議只反序列化來自信任來源的資料!
Shelve:物件持久化的簡易方案
shelve模組建立在pickle之上,提供了一個簡單的鍵值對儲存方式,可以將Python物件持久化到磁碟。你可以把它想像成一個持久化的字典。
Shelve的使用範例
import shelve
# 建立或開啟一個shelve檔案
with shelve.open("my_shelf") as shelf:
# 儲存資料
shelf["name"] = "玄貓"
shelf["age"] = 30
shelf["city"] = "台北"
# 讀取資料
with shelve.open("my_shelf") as shelf:
name = shelf["name"]
age = shelf["age"]
print(name, age)
內容解密:
shelve.open(filename): 開啟一個shelve檔案。如果檔案不存在,則建立一個新的檔案。shelf[key] = value: 將資料儲存到shelve檔案中,就像操作字典一樣。
Shelve的優缺點
- 優點
- 使用簡單,類別似字典操作
- 方便地持久化Python物件
- 缺點
- 根據
pickle,存在相同的安全風險 - 不適合高併發的應用場景
- 檔案大小可能隨著資料的增長而變得很大
- 根據
DBM:輕量級資料函式庫的選擇
dbm(Database Manager)是Python中用於操作類別Unix DBM資料函式庫的模組。它提供了一種簡單的方式來儲存和檢索字串鍵值對,適用於小型資料的持久化儲存。
DBM使用範例
import dbm
# 建立或開啟DBM資料函式庫
with dbm.open('my_db', 'c') as db:
# 儲存資料 (鍵和值都必須是bytes)
db[b'name'] = b'BlackCat'
db[b'age'] = b'30']
# 檢索資料
name = db[b'name']
age = db[b'age']
print(name.decode('utf-8'), age.decode('utf-8'))
內容解密:
dbm.open('my_db', 'c'): 開啟或建立DBM資料函式庫檔案。'c'模式表示如果資料函式庫不存在則建立。- 鍵和值都必須是位元組字串(bytes),因此需要使用
b'...'定義。 - 從資料函式庫中檢索到的值也是位元組字串,需要使用
.decode('utf-8')解碼為字串。
DBM的優缺點
- 優點:
- 簡單易用,適合儲存小型資料。
- 不需要額外的伺服器或設定。
- 缺點:
- 僅支援字串鍵值對,不支援複雜資料結構。
- 功能較為有限,不適合大型或複雜的應用。
- 不同的DBM實作(如
dbm.gnu、dbm.ndbm)可能在不同系統上有不同的行為。
如何選擇?
選擇哪種序列化方法取決於你的具體需求:
- JSON: 適合於需要跨平台、跨語言交換資料的場景,例如Web API。
- Pickle: 適合於儲存Python物件,但要注意安全性風險。
- Shelve: 適合於簡單的物件持久化,但不適合高併發應用。
- DBM: 適合小型、簡單的字串鍵值對儲存,不需要複雜的資料結構。
在實際應用中,玄貓建議根據資料的複雜度、安全需求和效能要求,綜合考慮各種方案,選擇最適合的序列化方法。