使用 Python 操作 Redis 數(shù)據(jù)庫
1. 簡(jiǎn)介
Redis 是是一個(gè)高性能的 key-value 數(shù)據(jù)庫。Redis 支持?jǐn)?shù)據(jù)的持久化,可以將內(nèi)存中的數(shù)據(jù)保存在磁盤中,重啟的時(shí)候可以再次加載進(jìn)行使用。 Redis不僅僅支持簡(jiǎn)單的 key-value 類型的數(shù)據(jù),同時(shí)還提供 list、set、zset、hash 等數(shù)據(jù)結(jié)構(gòu)的存儲(chǔ)。
Python 程序要訪問 Redis,需要使用第三方模塊 redis。
2. 安裝模塊 redis
redis 是 python 訪問 Redis 數(shù)據(jù)庫的模塊。首先檢查是否已經(jīng)安裝了 redis 模塊,在 python 交互模式下 import redis,如下所示:
>>> import redis
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'redis'
如果出現(xiàn)錯(cuò)誤:ModuleNotFoundError,則表示還沒有安裝 redis,使用 pip3 install mysql 安裝 redis,如下所示:
$ pip3 install redis
Collecting redis
...
Installing collected packages: redis
Successfully installed redis-3.5.3
3. 連接 redis 數(shù)據(jù)庫
使用 redis.Redis() 方法連接 redis 數(shù)據(jù)庫,示例如下:
>>> import redis
>>> db = redis.Redis(host='localhost')
>>> db.set('name', 'ZhangSan')
True
>>> db.get('name')
b'ZhangSan'
- 在第 1 行,引入 redis 模塊
- 在第 2 行,使用 redis.Redis() 方法連接 redis 數(shù)據(jù)庫,返回一個(gè)數(shù)據(jù)庫連接對(duì)象 db
- 在第 3 行,設(shè)置鍵 ‘name’ 的值為 ‘ZhangSan’
- 在第 5 行,獲取鍵 ‘name’ 的值
- 在第 6 行,redis 數(shù)據(jù)庫返回的是字節(jié)對(duì)象 b’ZhangSan’,而不是字符串 ‘ZhangSan’
在默認(rèn)情況下,redis 返回的結(jié)果是字節(jié)對(duì)象,通過設(shè)定參數(shù) decode_responses=True 使 redis 返回字符串。示例如下:
>>> import redis
>>> db = redis.Redis(host='localhost', decode_responses=True)
>>> db.set('name', 'ZhangSan')
True
>>> db.get('name')
'ZhangSan'
- 在第 2 行,使用 decode_responses=True 的方式連接 redis 數(shù)據(jù)庫
- 在第 6 行,redis 數(shù)據(jù)庫返回的是字符串 ‘ZhangSan’,而不是字節(jié)對(duì)象 b’ZhangSan’
在接下來的小節(jié)中,我們使用 decode_responses=True 的方式連接 redis 數(shù)據(jù)庫,通過數(shù)據(jù)庫連接對(duì)象 db 向 redis 數(shù)據(jù)庫發(fā)送命令。以上連接 redis 數(shù)據(jù)庫的代碼將不再重復(fù)。
4. 根據(jù)鍵訪問
4.1 設(shè)置和獲取一個(gè)鍵
>>> db.set('name', 'imooc')
True
>>> db.get('name')
'imooc'
- 在第 1 行,設(shè)置鍵 ‘name’ 的值為 ‘imooc’
- 在第 3 行,獲取鍵 ‘name’ 的值
4.2 設(shè)置和獲取多個(gè)鍵
>>> db.mset({'name': 'ZhangSan', 'age': 30})
True
>>> db.mget('name', 'age')
['ZhangSan', '30']
>>> db.mget(['name', 'age'])
['ZhangSan', '30']
- 在第 1 行,設(shè)置兩個(gè)鍵
- 設(shè)置鍵 ‘name’ 的值為 ‘ZhangSan’
- 設(shè)置鍵 ‘a(chǎn)ge’ 的值為 30
- 在第 3 行,獲取兩個(gè)鍵的值
- mget 返回一個(gè)記錄了兩個(gè)鍵值的數(shù)組
- 在第 5 行,獲取兩個(gè)鍵的值的另一種調(diào)用方式
4.2 刪除鍵
>>> db.set('name', 'ZhangSan')
>>> db.get('name')
'ZhangSan'
>>> db.delete('name')
1
>>> db.get('name')
>>> db.get('name') == None
True
- 在第 1 行,設(shè)置鍵 ‘name’ 的值為 ‘ZhangSan’
- 在第 4 行,使用 delete() 方法刪除鍵 ‘name’
- 刪除鍵 ‘name’ 后,db.get(‘name’) 返回 None
5. 訪問字符串
5.1 獲取字符串的長(zhǎng)度
>>> db.set('name', 'idcbgp.cn')
True
>>> db.strlen('name')
13
- 在第 1 行,設(shè)置鍵 ‘name’ 的值為字符串 ‘idcbgp.cn’
- 在第 3 行,通過 strlen() 方法獲取鍵 ‘name’ 的值的長(zhǎng)度
5.2 獲取字符串的子串
>>> db.getrange('name', 0, 2)
'www'
>>> db.getrange('name', 4, 8)
'imooc'
>>> db.getrange('name', 10, 12)
'com'
>>>
- 在第 1 行,獲取字符串中范圍為 [0, 2] 的子串,即 ‘www’
- 在第 3 行,獲取字符串中范圍為 [4, 8] 的子串,即 ‘imooc’
- 在第 5 行,獲取字符串中范圍為 [10, 12] 的子串,即 ‘com’
5.3 設(shè)置字符串的子串
>>> db.setrange('name', 4, 'IMOOC')
13
>>> db.get('name')
'idcbgp.cn'
- 在第 1 行,將字符串中從 4 開始的子串 ‘imooc’,替換為 ‘IMOOC’
6. 訪問列表
6.1 創(chuàng)建列表
>>> db.rpush('url', 'www')
1
>>> db.rpush('url', 'imooc')
2
>>> db.rpush('url', 'com')
3
- 方法 rpush(list, value) 將值 value 添加到列表 list 的尾部
- 如果列表 list 不存在,會(huì)創(chuàng)建一個(gè)空列表
- 在第 1 行,創(chuàng)建一個(gè)列表 url,將字符串 ‘www’ 添加到列表的尾部
- 在第 2 行,將字符串 ‘imooc’ 添加到列表的尾部
- 在第 3 行,將字符串 ‘com’ 添加到列表的尾部
6.2 訪問列表
>>> db.llen('url')
3
>>> db.lindex('url', 0)
'www'
>>> db.lindex('url', 1)
'imooc'
>>> db.lindex('url', 2)
'com'
- 在第 1 行,方法 llen(‘url’) 返回列表 url 的長(zhǎng)度
- 在第 3 行,llindex(‘url’, 0) 返回列表 url 中第 0 項(xiàng)的數(shù)據(jù)
- 在第 5 行,llindex(‘url’, 1) 返回列表 url 中第 1 項(xiàng)的數(shù)據(jù)
- 在第 7 行,llindex(‘url’, 2) 返回列表 url 中第 2 項(xiàng)的數(shù)據(jù)
6.3 獲取指定范圍的元素
>>> db.lrange('url', 0, 1)
['www', 'imooc']
>>> db.lrange('url', 0, 2)
['www', 'imooc', 'com']
- lrange(start, stop) 返回列表中指定區(qū)間 [start, stop] 內(nèi)的元素
- 在第 1 行,獲取列表 url 中范圍 [0, 1] 內(nèi)的 2 項(xiàng)元素
- 在第 3 行,獲取列表 url 中范圍 [0, 2] 內(nèi)的 3 項(xiàng)元素
6.4 在列表中插入數(shù)據(jù)
>>> db.lrange('url', 0, 2)
['www', 'imooc', 'com']
>>> db.linsert('url', 'after', 'www', '.')
4
>>> db.linsert('url', 'before', 'com', '.')
5
>>> db.lrange('url', 0, 4)
['www', '.', 'imooc', '.', 'com']
- 在第 3 行,在數(shù)據(jù)項(xiàng) ‘www’ 的后面,插入數(shù)據(jù)項(xiàng) ‘.’
- 在第 5 行,在數(shù)據(jù)項(xiàng) ‘com’ 的前面,插入數(shù)據(jù)項(xiàng) ‘.’
- 在第 8 行,結(jié)果顯示
- 在 ‘www’ 和 ‘imooc’ 之間增加了一項(xiàng) ‘.’
- 在 ‘imooc’ 和 ‘com’ 之間增加了一項(xiàng) ‘.’
6.5 修改列表
>>> db.lindex('url', 1)
'imooc'
>>> db.lset('url', 1, 'IMOOC')
True
>>> db.lindex('url', 1)
'IMOOC'
- 在第 1 行,顯示列表 ‘url’ 的第 1 項(xiàng)內(nèi)容為 ‘imooc’
- 在第 3 行,將列表 ‘url’ 的第 1 項(xiàng)內(nèi)容修改為 ‘IMOOC’
- 在第 5 行,顯示列表 ‘url’ 的第 1 項(xiàng)內(nèi)容為 ‘IMOOC’
6.6 將列表作為堆棧
>>> db.rpush('stack', 'www')
1
>>> db.rpush('stack', 'imooc')
2
>>> db.rpush('stack', 'com')
3
>>> db.llen('stack')
3
- 方法 rpush(list, value) 將數(shù)據(jù)增加到列表 list 尾部,相當(dāng)于堆棧的 push 操作
- 將 3 個(gè)字符串 ‘www’、‘imooc’、‘com’ 依次壓入到堆棧 stack 中
- 此時(shí)堆棧 stack 的長(zhǎng)度為 3
>>> db.rpop('stack')
'com'
>>> db.rpop('stack')
'imooc'
>>> db.rpop('stack')
'www'
>>> db.llen('stack')
0
- 方法 rpop(list) 將數(shù)據(jù)從列表 list 尾部刪除,相當(dāng)于堆棧的 pop 操作
- 從堆棧 stack 中依次彈出 ‘com’、‘imooc’、‘www’
- 此時(shí)堆棧 stack 的長(zhǎng)度為 0
7. 訪問集合
7.1 創(chuàng)建集合
>>> db.sadd('set', 'a')
1
>>> db.sadd('set', 'b')
1
>>> db.sadd('set', 'c')
1
- 方法 sadd(set, value) 向集合 set 中添加元素 value
- 如果集合 set 不存在,則創(chuàng)建一個(gè)集合
- 在第 1 行,向集合 ‘set’ 添加元素 ‘a(chǎn)’
- 在第 3 行,向集合 ‘set’ 添加元素 ‘b’
- 在第 5 行,向集合 ‘set’ 添加元素 ‘c’
7.2 獲取集合的成員
>>> db.scard('set')
3
>>> db.smembers('set')
{'b', 'c', 'a'}
- 在第 1 行,使用方法 scard(‘set’) 獲取集合的元素的數(shù)量
- 在第 3 行,使用方法 smembers(‘set’) 獲取集合的所有元素
>>> db.sismember('set', 'b')
True
>>> db.sismember('set', 'd')
False
- 在第 1 行,使用方法 sismember(‘set’, ‘b’) 檢查集合 ‘set’ 是否包含 ‘b’
- 在第 3 行,使用方法 sismember(‘set’, ‘d’) 檢查集合 ‘set’ 是否包含 ‘d’
7.3 求集合的交、并、差
>>> db.sadd('set2', 'b')
1
>>> db.sadd('set2', 'c')
1
>>> db.sadd('set2', 'd')
1
- 創(chuàng)建集合 ‘set2’,向集合 ‘set2’ 中添加元素 ‘b’、‘c’、‘d’
>>> db.smembers('set')
{'a', 'b', 'c'}
>>> db.smembers('set2')
{'b', 'd', 'c'}
- 顯示集合 ‘set’ 與 集合 ‘set2’ 包含的成員
>>> db.sinter('set', 'set2')
{'b', 'c'}
>>> db.sunion('set', 'set2')
{'a', 'b', 'd', 'c'}
- db.sinter(‘set’, ‘set2’) 求取集合的交集
- db.sunion(‘set’, ‘set2’) 求取集合的并集
>>> db.sdiff('set', 'set2')
{'a'}
>>> db.sdiff('set2', 'set')
{'d'}
- db.sdiff(‘set’, ‘set2’) 求取集合的差集
- 在 ‘set’ 中出現(xiàn),在 ‘set2’ 中沒有出現(xiàn)的元素構(gòu)成的集合
- db.sdiff(‘set2’, ‘set’) 求取集合的差集
- 在 ‘set2’ 中出現(xiàn),在 ‘set’ 中沒有出現(xiàn)的元素構(gòu)成的集合
8. 訪問哈希
8.1 創(chuàng)建哈希表
>>> db.hset('person', 'name', 'ZhangSan')
1
>>> db.hset('person', 'age', 20)
1
- 方法 hset(hash_table, key, value),向哈希表 hash_table 增加一組鍵值對(duì),鍵為 key、值為 value
- 如果哈希表 hash_table 不存在,則創(chuàng)建一個(gè)新的哈希表
- 創(chuàng)建一個(gè)哈希表 person,描述一個(gè)人,包括兩項(xiàng)屬性:name 和 age
- 在第 1 行,為哈希表 person 增加一組鍵值對(duì):鍵為 ‘name’、值為 ‘ZhangSan’
- 在第 3 行,為哈希表 person 增加一組鍵值對(duì):鍵為 ‘a(chǎn)ge’、值為 20
>>> db.hlen('person')
2
- 方法 hlen(hash_table) 獲取 hash_table 中鍵值對(duì)的數(shù)目
8.2 訪問哈希表
>>> db.hget('person', 'name')
'ZhangSan'
>>> db.hget('person', 'age')
'20'
- 方法 hget(hash_table, key) 獲取哈希表 hash_table 中鍵為 key 對(duì)應(yīng)的值
- 在第 1 行,獲取哈希表 ‘person’ 中鍵為 ‘name’ 的值
- 在第 3 行,獲取哈希表 ‘person’ 中鍵為 ‘a(chǎn)ge’ 的值
>>> db.hexists('person', 'name')
True
>>> db.hexists('person', 'gender')
False
- 方法 hexists(hash_table, key) 返回哈希表 hash_table 是否包含鍵 key
- 在第 1 行,獲取哈希表 ‘person’ 是否包含 ‘name’
- 在第 3 行,獲取哈希表 ‘person’ 是否包含 ‘gender’
8.3 獲取所有的鍵和值
>>> db.hkeys('person')
['name', 'age']
>>> db.hvals('person')
['ZhangSan', '20']
>>> db.hgetall('person')
{'name': 'ZhangSan', 'age': '20'}
- 方法 hkeys(hash_table) 返回 hash_table 中所有的鍵
- 方法 hvals(hash_table) 返回 hash_table 中所有的值
- 方法 hgetall(hash_table) 返回一個(gè)字典,描述 hash_table 中所有的鍵和值
8.4 遍歷哈希表
>>> keys = db.hkeys('person')
>>> for key in keys:
... val = db.hget('person', key)
... print('%s:%s' % (key, val))
...
name:ZhangSan
age:20
- 在第 1 行,通過 hkeys() 方法獲取所有的鍵
- 在第 2 行,使用 for 循環(huán)遍歷所有的鍵
- 在第 3 行,使用 hget() 方法獲取指定鍵對(duì)應(yīng)的值
>>> dict = db.hgetall('person')
>>> for key,val in dict.items():
... print('%s:%s' % (key, val))
...
name:ZhangSan
age:20
- 在第 1 行,通過 hgetall() 方法獲取所有的鍵值對(duì),該方法返回一個(gè)字典
- 遍歷 hgetall() 返回的字典
8.5 增加鍵和刪除鍵
>>> db.hset('person', 'gender', 'female')
1
>>> db.hgetall('person')
{'name': 'ZhangSan', 'age': '20', 'gender': 'female'}
>>> db.hdel('person', 'gender')
1
>>> db.hgetall('person')
{'name': 'ZhangSan', 'age': '20'}
- 在第 1 行,為哈希表 ‘person’ 增加一個(gè)鍵 ‘gender’,值為 ‘female’
- 在第 3 行,使用方法 hgetall(‘person’) 顯示哈希表 ‘person’ 的鍵值對(duì)
- 已經(jīng)增加了一個(gè)鍵 ‘gender’
- 在第 5 行,使用方法 hdel(‘person’, ‘gender’) 刪除哈希表 ‘person’ 中的鍵 ‘gender’
- 在第 7 行,使用方法 hgetall(‘person’) 顯示哈希表 ‘person’ 的鍵值對(duì)
- 已經(jīng)刪除了鍵 ‘gender’