Python Tutorial 第三堂(3)永續化機制
Python Tutorial 第三堂(2)資料處理函式 << 前情 在 Python Tutorial 第一堂(4)中談過基本輸入輸出,除了利用基本 I/O 來保存運算結果之外,Python 中還提供了一些方式,可以直接保存物件狀態,在下次重新執行程式時讀取以恢復運算時必要的資料,在這邊要介紹幾個方式,像是 …
除此之外,你還可以透過第三方程式庫,進行物件關聯對應(Object-Relational Mapping),像是 SQLAlchemy、SQLObject,由於時間的關係,ORM 沒辦法在這節課做說明,不過稍後介紹 Django 時,會看到一些 ORM 的實際例子。 marshal、pickle 與 cPickle在物件序列化方面, 一般來說,如果要序列化 Python 物件,使用
來看看使用 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(' ', '_') + '.pkl' 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: 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: ... 這次是讀取,因此你要用 filename = 'PyConTutorial2013.pkl' dvd1 = DVD('PyCon Tutorial', 2013, 1, 'Justin Lin') dvd1.save() dvd2 = DVD('PyCon Tutorial') dvd2.load() print dvd2 DBMdbm 為柏克萊大學發展的檔案型資料庫,Python 的 在這邊直接轉貼 anydbm — Generic access to DBM-style databases 中的範例程式碼作個示範: import anydbm # Open database, creating it if necessary. db = anydbm.open('cache', 'c') # Record some values db['www.python.org'] = 'Python Website' db['www.cnn.com'] = 'Cable News Network' # Loop through contents. Other dictionary methods # such as .keys(), .values() also work. for k, v in db.iteritems(): print k, '\t', v # Storing a non-string key or value will raise an exception (most # likely a TypeError). db['www.yahoo.com'] = 4 # Close when done. db.close() shelve 模組
class DvdDao: def __init__(self, shelve_name): self.shelve_name = shelve_name def save(self, dvd): shelve_db = None try: shelve_db = shelve.open(self.shelve_name) shelve_db[dvd.title] = (dvd.year, dvd.duration, dvd.director_id) shelve_db.sync() finally: if shelve_db is not None: shelve_db.close()
def all(self): shelve_db = None try: shelve_db = shelve.open(self.shelve_name) return [DVD(title, *shelve_db[title]) for title in sorted(shelve_db, key=str.lower)] finally: if shelve_db is not None: shelve_db.close() return [] def load(self, title): shelve_db = None try: shelve_db = shelve.open(self.shelve_name) if title in shelve_db: return DVD(title, *shelve_db[title]) finally: if shelve_db is not None: shelve_db.close() return None def remove(self, title): shelve_db = None try: shelve_db = shelve.open(self.shelve_name) del shelve_db[title] shelve_db.sync() finally: if shelve_db is not None: shelve_db.close() 以下是個使用 filename = 'dvd_library.slv' dao = DvdDao(filename) dvd1 = DVD('PyCon Tutorial 2012', 2012, 1, 'Justin Lin') dvd2 = DVD('PyCon Tutorial 2013', 2013, 1, 'Justin Lin') dao.save(dvd1) dao.save(dvd2) print dao.all() print dao.load('PyCon Tutorial 2012') dao.remove('PyCon Tutorial 2013') print dao.all() DB-API 2.0(PEP 249)為 Python 中存取資料庫的標準介面,就我的認知而言,其角色應該是類似於 Java 中的 JDBC。Python 中的 以下直接列出範例程式碼,程式很簡單,應該一目瞭然,API 細節可參考 sqlite3 — DB-API 2.0 interface for SQLite databases。 def connect(name): create = not os.path.exists(name) conn = sqlite3.connect(name) if create: cursor = conn.cursor() cursor.execute("CREATE TABLE directors (" "id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE NOT NULL, " "name TEXT UNIQUE NOT NULL)") cursor.execute("CREATE TABLE dvds (" "id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE NOT NULL, " "title TEXT NOT NULL, " "year INTEGER NOT NULL, " "duration INTEGER NOT NULL, " "director_id INTEGER NOT NULL, " "FOREIGN KEY (director_id) REFERENCES directors)") conn.commit() return conn def add_dvd(conn, title, year, duration, director): director_id = get_and_set_director(conn, director) cursor = conn.cursor() cursor.execute("INSERT INTO dvds " "(title, year, duration, director_id) " "VALUES (?, ?, ?, ?)", (title, year, duration, director_id)) conn.commit() def get_and_set_director(conn, director): director_id = get_director_id(conn, director) if director_id is not None: return director_id cursor = conn.cursor() cursor.execute("INSERT INTO directors (name) VALUES (?)", (director,)) conn.commit() return get_director_id(conn, director) def get_director_id(conn, director): cursor = conn.cursor() cursor.execute("SELECT id FROM directors WHERE name=?", (director,)) fields = cursor.fetchone() return fields[0] if fields is not None else None def all_dvds(conn): cursor = conn.cursor() sql = ("SELECT dvds.title, dvds.year, dvds.duration, " "directors.name FROM dvds, directors " "WHERE dvds.director_id = directors.id" " ORDER BY dvds.title") cursor.execute(sql) return [(str(fields[0]), fields[1], fields[2], str(fields[3])) for fields in cursor] def all_directors(conn): cursor = conn.cursor() cursor.execute("SELECT name FROM directors ORDER BY name") return [str(fields[0]) for fields in cursor] 以下是個存取資料庫的例子: db_name = 'dvd_library.sqlite3' conn = connect(db_name) add_dvd(conn, 'Python Tutorial 2013', 2013, 1, 'Justin') print all_directors(conn) print all_dvds(conn) 練習 8:永續化機制 在 Lab 檔案中有個 lab/exercises/exercise8,當中有 pickle、shelve、sql 三個資料夾,分別是上頭三個程式範例,不過程式碼內容不完整,請任選你想要練習的對象,按加上頭列出的範例程式碼,就不齊全的部份補齊。 完成這個練習後,第三堂應該時間就差不多到了,休息一下,接下來的第三堂課要來認識 Python 的 Web 框架 … 參考資源
* http://www.python.org/~guido/
* http://docs.python.org/2.7/
* http://docs.python.org/2.7/library/functions.html
* http://docs.python.org/2/library/pickle.html 後續 >> Python Tutorial 第四堂(1)Django 起步走
|