Python3與redis交互,保存的是字符串,取出來是bytes類型問題
Python3與redis交互,保存的是字符串,取出來是bytes
原因
在python3中redis連接包讀取數(shù)據(jù)默認(rèn)返回byte類型。
存進(jìn)去的是字符串類型的數(shù)據(jù),取出來卻是字節(jié)類型的。
Python2取出來的就是字符串類型的。
import platform import redis if "inux" in platform.system(): print("檢測到是服務(wù)器環(huán)境,啟動(dòng)redis內(nèi)網(wǎng)鏈接") IP = "xxx.xx.x.xx" PORT = 6379 else: IP = "xxx.xxx.xxx.xx" PORT = 6379 # 存進(jìn)去的是字符串類型的數(shù)據(jù),取出來卻是字節(jié)類型的 redisPool1 = redis.ConnectionPool(host=IP, port=PORT, db=1, password="xxxxxxx") if __name__ == '__main__': client = redis.Redis(connection_pool=redisPool1 ) client.set("ACCESS_TOKEN", "ABC123456", 60 * 60) token = client.get("ACCESS_TOKEN") print(token) # b'ABC123456' print(type(token)) # <class 'bytes'>
解決方法
連接redis的時(shí)候,加上decode_responses=True或者每次取出來都decode一下(太麻煩,不推薦)
import platform import redis if "inux" in platform.system(): print("檢測到是服務(wù)器環(huán)境,啟動(dòng)redis內(nèi)網(wǎng)鏈接") IP = "xxx.xx.x.xx" PORT = 6379 else: IP = "xxx.xxx.xxx.xx" PORT = 6379 # 存進(jìn)去的是字符串類型的數(shù)據(jù),取出來也是字符型 redisPool1 = redis.ConnectionPool(host=IP, port=PORT, db=1, password="xxxxxxx", decode_responses=True) if __name__ == '__main__': client = redis.Redis(connection_pool=redisPool1 ) client.set("ACCESS_TOKEN", "ABC123456", 60 * 60) token = client.get("ACCESS_TOKEN") print(token) # ABC123456 print(type(token)) # <class 'str'>
Redis-Python交互:編碼、連接、基本命令
在redis-py 3.0之后就不在支持使用傳統(tǒng)的‘Redis’客戶端類了。
StrictRedis 現(xiàn)在只是 Redis 的一個(gè)別名,現(xiàn)在這個(gè)連接更加python化。
例如,使用redis的字符串操作 setbit 和 getbit 來統(tǒng)計(jì)用戶活躍天數(shù):
''' 用Redis統(tǒng)計(jì)用戶上線次數(shù) 理解: A用戶 100010001000001 //活躍了4天 B用戶 111111111111111 //每日必到 ''' import redis from ..password import redis_passwd # 連接Redis,選擇 db0 r = redis.Redis(host='localhost', port=6379, password=redis_passwd, db=0) # A用戶,一年中,每3天上線一次 for i in range(0, 365, 3): r.setbit('usera', i, 1) # B用戶 每10天上線一次 for i in range(0, 365, 10): r.setbit('userb', i, 1) # 用戶列表 # "Returns a list of keys matching ``pattern``" userList = r.keys('user*') print(userList) Au = [] Nau = [] # 判斷是否為活躍用戶,(用戶,登錄天數(shù)) for u in userList: logincount = r.bitcount(u) if logincount > 100: Au.append((u, logincount)) else: Nau.append((u, logincount)) for u in Au: print(f'用戶{u[0]}: 活躍用戶, 共登錄{u[1]}天') for u in Nau: print(f'用戶{u[0]}: 非活躍用戶, 共登錄{u[1]}天')
編碼
PubSub對象遵循與其創(chuàng)建的客戶端實(shí)例相同的編碼方式。在發(fā)送到Redis之前,將使用客戶端上指定的字符集對任何使用unicode編碼的通道或模式進(jìn)行編碼。
如果客戶端的decode_responses標(biāo)志設(shè)置為False(默認(rèn)值),則消息字典中的channel,pattern和data值將是字節(jié)字符串(Python2的str,Python3的bytes)。
如果客戶端的decode_responses為True,則它們值將使用客戶端的字符集自動(dòng)解碼為unicode字符串。
默認(rèn),bytes類型:
>>> import redis >>> r = redis.Redis(host='localhost', port=6379, password='***') >>> r.set('str', 'time') True >>> ret = r.get('name') >>> print(ret, type(ret)) b'Redis' <class 'bytes'> >>>
修改為str:
>>> import redis >>> r = redis.Redis(host='localhost', port=6379, password='***', decode_responses=True) >>> r.set('str', 'time') True >>> ret = r.get('name') >>> print(ret, type(ret)) Redis <class 'str'>
默認(rèn)redis入庫編碼是utf-8,如果要修改的話,需要指明 charset和 decode_responsers 為True。
使用GBK編碼:
>>> r2 = redis.Redis(host='localhost', port=6379, password='***', charset='GBK' ,decode_responses=True) >>> r2.set('greet', '你好') True >>> r2.get('greet') '你好'
連接池
redis使用connection pool來管理對一個(gè)redis server 的所有連接,避免每次建立、釋放連接的開銷。
默認(rèn),每個(gè)Redis實(shí)例都會(huì)維護(hù)一個(gè)自己的連接池。
可以直接建立一個(gè)連接池,然后作為參數(shù)創(chuàng)建Redis實(shí)例,這樣就可以實(shí)現(xiàn)多個(gè)Redis實(shí)例共享一個(gè)連接池。
""" 連接池 """ import redis from ..password import redis_passwd pool = redis.ConnectionPool(host='localhost', port=6379, db=0, password=redis_passwd) r = redis.Redis(connection_pool=pool) r.set('name', 'Redis') print(r.get('name')) # 輸出結(jié)果 b'Redis'
連接方式
ConnectionPools管理一組Connection實(shí)例。
redis-py有兩種類型的連接。默認(rèn)值連接方式是基于TCP套接字的常規(guī)連接。
UnixDomainSocketConnection允許在與服務(wù)器相同的設(shè)備上運(yùn)行的客戶端通過unix域套接字進(jìn)行連接。
要使用UnixDomainSocketConnection連接,只需將unix_socket_path參數(shù)傳遞給unix域套接字文件,該參數(shù)是一個(gè)字符串。
此外,請確保在redis.conf文件中定義了unixsocket參數(shù),默認(rèn)注釋掉了。
# Unix socket. # # Specify the path for the Unix socket that will be used to listen for # incoming connections. There is no default, so Redis will not listen # on a unix socket when not specified. # # unixsocket /var/run/redis/redis-server.sock # unixsocketperm 700
>>> r = redis.Redis(unix_socket_path='/tmp/redis.sock')
操作
key操作
delete(self, *names)
:刪除鍵dump(self, name)
:序列化給定 key ,并返回被序列化的值exists(self, *names)
:檢查給定 key 是否存在。expire(self, name, time)
:為給定 key 設(shè)置過期時(shí)間,以秒計(jì),time為整數(shù)Python timedelta 對象。expireat(self, name, when)
:EXPIREAT 的作用和 EXPIRE 類似,都用于為 key 設(shè)置過期時(shí)間。 不同在于 EXPIREAT 命令接受的時(shí)間參數(shù)是 UNIX 時(shí)間戳(unix timestamp)或python datetime對象pexpire(self, name, time)
:類似expire, 時(shí)間以毫秒計(jì)pexpireat(self, name, when)
:類似expireat, 時(shí)間以毫秒計(jì)keys(self, pattern=’*’)
:查找所有符合給定模式( pattern)的 keymove(self, name, db)
:將當(dāng)前數(shù)據(jù)庫的 key 移動(dòng)到給定的數(shù)據(jù)庫 db 當(dāng)中persist(self, name)
:移除 key 的過期時(shí)間,key 將持久保持。pttl(self, name)
:以毫秒為單位返回 key 的剩余的過期時(shí)間ttl(self, name)
:以秒為單位,返回給定 key 的剩余生存時(shí)間(TTL, time to live)randomkey(self)
:從當(dāng)前數(shù)據(jù)庫中隨機(jī)返回一個(gè) keyrename(self, src, dst)
:修改 key 的名稱renamenx(self, src, dst)
:當(dāng)dst不存在時(shí),可以使用它作為src的名字type(self, name)
:返回 key 所儲(chǔ)存的值的類型
服務(wù)器操作
bgrewriteaof(self)
:異步執(zhí)行一個(gè) AOF(AppendOnly File) 文件重寫操作bgsave(self)
:在后臺(tái)異步保存當(dāng)前數(shù)據(jù)庫的數(shù)據(jù)到磁盤client_kill(self, address)
:關(guān)閉客戶端連接client_list(self, _type=None)
:獲取連接到服務(wù)器的客戶端連接列表client_getname(self)
:獲取連接的名稱client_id(self)
:獲取當(dāng)前連接的idclient_setname(self, name)
:設(shè)置當(dāng)前連接的名稱client_pause(self, timeout)
:在指定時(shí)間內(nèi)終止運(yùn)行來自客戶端的命令(毫秒)client_unblock(self, client_id, error=False)
:解除指定連接id的客戶端阻塞config_get, config_set,config_rewrite
:讀寫redis.conf配置文件config_resetstat(self)
:重置 INFO 命令中的某些統(tǒng)計(jì)數(shù)據(jù)dbsize(self)
:返回當(dāng)前數(shù)據(jù)庫的 key 的數(shù)量debug_object(self, key)
:獲取 key 的調(diào)試信息echo(self, value)
:打印字符串flushall(self, asynchronous=False)
:清空所有數(shù)據(jù)庫flushdb(self, asynchronous=False)
:清空當(dāng)前數(shù)據(jù)庫info(self, section=None)
:獲取 Redis 服務(wù)器的各種信息和統(tǒng)計(jì)數(shù)值lastsave(self)
:返回最近一次 Redis 成功將數(shù)據(jù)保存到磁盤上的時(shí)間,以 UNIX 時(shí)間戳格式表示
save(self):同步保存數(shù)據(jù)到硬盤
ping(self)
:查看服務(wù)是否運(yùn)行migrate
(self, host, port, keys, destination_db, timeout,copy=False, replace=False, auth=None): 數(shù)據(jù)庫遷移shutdown
(self, save=False, nosave=False):異步保存數(shù)據(jù)到硬盤,并關(guān)閉服務(wù)器slaveof
(self, host=None, port=None):將當(dāng)前服務(wù)器轉(zhuǎn)變?yōu)橹付ǚ?wù)器的從屬服務(wù)器(slave server)slowlog_get
(self, num=None):管理 redis 的慢日志wait
(self, num_replicas, timeout):Redis同步復(fù)制
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
PyQt轉(zhuǎn)換路徑中的斜杠(斜杠(/)與反斜杠(\)轉(zhuǎn)換)
本文主要介紹了PyQt轉(zhuǎn)換路徑中的斜杠(斜杠(/)與反斜杠(\)轉(zhuǎn)換),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07解決Pycharm中恢復(fù)被exclude的項(xiàng)目問題(pycharm source root)
今天小編就為大家分享一篇解決Pycharm中恢復(fù)被exclude的項(xiàng)目問題(pycharm source root),具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-02-02Python softmax實(shí)現(xiàn)及數(shù)值穩(wěn)定性詳解
這篇文章主要為大家介紹了Python softmax實(shí)現(xiàn)及數(shù)值穩(wěn)定性詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07python中有關(guān)時(shí)間日期格式轉(zhuǎn)換問題
這篇文章主要介紹了python中有關(guān)時(shí)間日期格式轉(zhuǎn)換問題,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-12-12Python基于OpenCV實(shí)現(xiàn)人臉檢測并保存
這篇文章主要介紹了Python基于OpenCV實(shí)現(xiàn)人臉檢測并保存,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-07-07Python編程實(shí)現(xiàn)小姐姐跳舞并生成詞云視頻示例
本文用Python做了一個(gè)詞云視頻,以另一種角度來看小姐姐跳舞視頻左半部分是小姐姐跳舞視頻,右半部分是根據(jù)動(dòng)作生成的的詞云視頻,有需要的朋友可以借鑒參考下2021-10-10