像對象一樣對待數(shù)據(jù)
入門教程、案例源碼、學習資料、讀者群
請訪問: python666.cn
咱們編程教室有不少同學,學完了基礎課程,掌握了一定的編程能力,開始做項目了。然后很可能遇到一個問題:管理數(shù)據(jù)。課程里有講過用文件保存數(shù)據(jù),還有 pickle、csv 等模塊輔助。但對于稍微復雜一點的數(shù)據(jù),往往不夠方便。成熟的解決方案就是使用數(shù)據(jù)庫。
估計每個剛剛使用數(shù)據(jù)庫的人都會被坑得遍體鱗傷。對于一個剛剛學會 Python 不久的開發(fā)新手來說,使用數(shù)據(jù)庫的 SQL 語句幾乎相當于再學一種新的語言。雖然 sqlite、pymysql 等模塊提供了與數(shù)據(jù)的連接,但仍然需要自己去拼接 SQL 語句。Python 語法和 SQL 語法、各種引號、百分號、轉義字符混雜在一起的酸爽,用過的人都忘不了。
所以實際開發(fā)中,如無特殊需求,一般不會直接寫 SQL,而是用更為方便的 ORM(對象關系映射,Object Relational Mapping)。顧名思義,就是將關系型數(shù)據(jù)庫與 Python 中的對象關聯(lián)起來,提供了一種操作數(shù)據(jù)的簡便方式,相當于對數(shù)據(jù)庫加了一層更友好的接口。
目前 Python 中比較流行的 ORM 解決方案有三種:
Django ORM。使用方便,但很難脫離 Django 單獨使用。
SQLAlchemy。功能強大,成熟可擴展,但學習門檻較高。
peewee。輕量,可擴展,易學習,但功能有限。
對于偏初級的小型項目,通常用不到很復雜的功能,這時候 peewee 或許是最好的選擇。今天我們就來重點介紹下 peewee 這個 Python ORM 庫。
> 安裝
pip install peewee
> 連接數(shù)據(jù)庫
以 SQLite 為例:
import peewee
db = peewee.SqliteDatabase('people.db')
db.connect()
people.db 是 SQLite 的數(shù)據(jù)庫文件,如果不存在會自己新建。
如果是 MySQL,要稍微復雜點,需再提供地址、用戶名、密碼等信息,并且必須先手動建好庫:
db = peewee.MySQLDatabase('people', host='127.0.0.1', user='root', passwd='', charset='utf8', port=3306)
特別要記住的一點是,代碼進行完所有數(shù)據(jù)庫操作后,要主動關閉數(shù)據(jù)庫:
db.close()
> 創(chuàng)建數(shù)據(jù)類型
既然是與對象關聯(lián),自然需要以面向對象的方式定義數(shù)據(jù)結構。我們假定一個表示人的類型 Person,包含姓名 name 和生日 birthday 兩個字段:
class Person(peewee.Model):
class Meta:
database = db
name = peewee.CharField()
birthday = peewee.DateField()
Person.create_table()
如果是用過 Django 的同學,對這個 Model 應該非常熟悉了。要注意的就是,需要在 Meta 里定義 database 為前面創(chuàng)建的數(shù)據(jù)庫。然后使用相應的 Field 類型定義字段即可。
> 新增數(shù)據(jù)對象
from datetime import date
# 方法1
uncle_bob = Person(name='Bob', birthday=date(1960, 1, 15))
uncle_bob.save()
# 方法2
Person.create(name='Crossin', birthday=date(1985, 5, 5))
直接創(chuàng)建數(shù)據(jù)對象,需要調(diào)用 save 方法保存到數(shù)據(jù)庫中。而使用 create 方法創(chuàng)建則不用。
> 查找數(shù)據(jù)對象
bob = Person.get(Person.name == 'Bob')
print(bob.name, bob.birthday)
# 獲取所有數(shù)據(jù)
for person in Person.select():
print(person.name)
注意這里的查找條件寫法,這與 Django 是不同的。查找還可以用 where 語句,這里不做演示,可以參考官方文檔。
> 修改數(shù)據(jù)對象
對于上一步找到的 bob 變量:
bob.name = 'Robert'
bob.save()
直接向屬性賦值,修改完記得要 save。
> 刪除數(shù)據(jù)對象
bob.delete_instance()
順便說句,一般不建議在數(shù)據(jù)庫里刪除數(shù)據(jù),因為數(shù)據(jù)刪了就不好找回來了,而且可能還會引發(fā)關聯(lián)數(shù)據(jù)的報錯。通常是增加一個 is_deleted 字段標記已刪除的內(nèi)容。(所以,不要以為在網(wǎng)上把發(fā)布過的內(nèi)容刪掉就真的不存在了)
> 創(chuàng)建關聯(lián)數(shù)據(jù)
在程序中,經(jīng)常會有一些具有關聯(lián)關系的數(shù)據(jù)。比如我們再創(chuàng)建一個寵物類 Pet,每個寵物有名字 name 和主人 owner。owner 對應的就是我們前面創(chuàng)建的 Person 類:
class Pet(peewee.Model):
class Meta:
database = db
owner = peewee.ForeignKeyField(Person, backref='pets')
name = peewee.CharField()
這樣一來,我們就可以很方便的通過寵物找到它的主人:
bob_kitty = Pet.create(owner=bob, name='Kitty')
bob_fido = Pet.create(owner=bob, name='Fido')
print(bob_kitty.owner.name)
也可以找到一個人養(yǎng)的所有寵物:
for pet in bob.pets:
print(pet.name)
以上就是 peewee 的基本操作,如果你了解面向對象,應該不難理解。這些例子取自其官方文檔的快速上手 Quickstart。雖然沒有像 Requests 那樣貼心地提供中文版,但也同樣足夠人性化。
地址:http://docs.peewee-orm.com/en/latest/peewee/quickstart.html
> 自動生成代碼
peewee 提供了一個功能,可以從已有的數(shù)據(jù)庫反向生成數(shù)據(jù)模型代碼。以 SQLite 為例:
python -m pwiz -e sqlite people.db > db.py
在你的數(shù)據(jù)庫文件所在路徑下執(zhí)行這條命令,就可以在 db.py 中自動生成代碼。

自動生成的代碼
在我們先前的案例中,有一些就使用了 peewee。比如 Python 高頻詞匯表(關鍵字:單詞)和押韻檢索工具(關鍵字:押韻)。在本公眾號(Crossin的編程教室)里回復相應關鍵字可查看文章及代碼。
最后提一下,除了使用 ORM 外,對于數(shù)據(jù)存儲還有一種解決方案,就是使用非關系型數(shù)據(jù)庫,比如 mongodb。盡管坑也不少,但對于簡單的數(shù)據(jù)存儲來說,它有個巨大的優(yōu)勢就是同 Python 內(nèi)置的 dict、list 等類型兼容良好,可以直接存取,讓你甚至感覺不到有數(shù)據(jù)庫的存在,也根本無需關心 SQL 語句。爬蟲實戰(zhàn)課程中的部分案例,就選擇了 mongodb 作為數(shù)據(jù)存儲方案。

本書從 Python 和 Excel 結合使用的角度講解處理分析數(shù)據(jù)的思路、方法與實戰(zhàn)應用。不論是希望從事數(shù)據(jù)分析崗位的學習者,還是其他職業(yè)的辦公人員,都可以通過本書的學習掌握 Python 分析數(shù)據(jù)的技能。書中創(chuàng)新性地將 ChatGPT 引入到教學當中,用 ChatGPT 答疑并提供實訓代碼,并介紹了使用 ChatGPT 輔助學習的一些實用技巧,給學習者帶來全新的學習方式。
公眾號的讀者朋友們購買后可在后臺聯(lián)系我,加入讀者交流群,Crossin會為你開啟陪讀模式,解答你在閱讀本書時的一切疑問。
_往期文章推薦_
