Python3与redis交互,保存的是字符串,取出来是bytes类型问题

 更新时间:2023年09月07日 09:15:01   作者:乐事原味~  
这篇文章主要介绍了Python3与redis交互,保存的是字符串,取出来是bytes类型问题,具有很好的参考价值,希望对大家有所帮助,

Python3与redis交互,保存的是字符串,取出来是bytes

原因

在python3中redis连接包读取数据默认返回byte类型。

存进去的是字符串类型的数据,取出来却是字节类型的。

Python2取出来的就是字符串类型的。

import platform
import redis
if "inux" in platform.system():
    print("检测到是服务器环境,启动redis内网链接")
    IP = "xxx.xx.x.xx"
    PORT = 6379
else:
    IP = "xxx.xxx.xxx.xx"
    PORT = 6379
# 存进去的是字符串类型的数据,取出来却是字节类型的
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的时候,加上decode_responses=True或者每次取出来都decode一下(太麻烦,不推荐)

import platform
import redis
if "inux" in platform.system():
    print("检测到是服务器环境,启动redis内网链接")
    IP = "xxx.xx.x.xx"
    PORT = 6379
else:
    IP = "xxx.xxx.xxx.xx"
    PORT = 6379
# 存进去的是字符串类型的数据,取出来也是字符型
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之后就不在支持使用传统的‘Redis’客户端类了。

StrictRedis 现在只是 Redis 的一个别名,现在这个连接更加python化。

例如,使用redis的字符串操作 setbit 和 getbit 来统计用户活跃天数:

'''
用Redis统计用户上线次数
理解:
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 = []
# 判断是否为活跃用户,(用户,登录天数)
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对象遵循与其创建的客户端实例相同的编码方式。在发送到Redis之前,将使用客户端上指定的字符集对任何使用unicode编码的通道或模式进行编码。

如果客户端的decode_responses标志设置为False(默认值),则消息字典中的channel,pattern和data值将是字节字符串(Python2的str,Python3的bytes)。

如果客户端的decode_responses为True,则它们值将使用客户端的字符集自动解码为unicode字符串。

默认,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'>

默认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来管理对一个redis server 的所有连接,避免每次建立、释放连接的开销。

默认,每个Redis实例都会维护一个自己的连接池。

可以直接建立一个连接池,然后作为参数创建Redis实例,这样就可以实现多个Redis实例共享一个连接池。

"""
连接池
"""
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'))
# 输出结果
b'Redis'

连接方式

ConnectionPools管理一组Connection实例。

redis-py有两种类型的连接。默认值连接方式是基于TCP套接字的常规连接。

UnixDomainSocketConnection允许在与服务器相同的设备上运行的客户端通过unix域套接字进行连接。

要使用UnixDomainSocketConnection连接,只需将unix_socket_path参数传递给unix域套接字文件,该参数是一个字符串。

此外,请确保在redis.conf文件中定义了unixsocket参数,默认注释掉了。

# 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 设置过期时间,以秒计,time为整数Python timedelta 对象。
  • expireat(self, name, when):EXPIREAT 的作用和 EXPIRE 类似,都用于为 key 设置过期时间。 不同在于 EXPIREAT 命令接受的时间参数是 UNIX 时间戳(unix timestamp)或python datetime对象
  • pexpire(self, name, time):类似expire, 时间以毫秒计
  • pexpireat(self, name, when):类似expireat, 时间以毫秒计
  • keys(self, pattern=’*’):查找所有符合给定模式( pattern)的 key
  • move(self, name, db):将当前数据库的 key 移动到给定的数据库 db 当中
  • persist(self, name):移除 key 的过期时间,key 将持久保持。
  • pttl(self, name):以毫秒为单位返回 key 的剩余的过期时间
  • ttl(self, name):以秒为单位,返回给定 key 的剩余生存时间(TTL, time to live)
  • randomkey(self):从当前数据库中随机返回一个 key
  • rename(self, src, dst):修改 key 的名称
  • renamenx(self, src, dst):当dst不存在时,可以使用它作为src的名字
  • type(self, name):返回 key 所储存的值的类型

服务器操作

  • bgrewriteaof(self):异步执行一个 AOF(AppendOnly File) 文件重写操作
  • bgsave(self):在后台异步保存当前数据库的数据到磁盘
  • client_kill(self, address):关闭客户端连接
  • client_list(self, _type=None):获取连接到服务器的客户端连接列表
  • client_getname(self):获取连接的名称
  • client_id(self):获取当前连接的id
  • client_setname(self, name):设置当前连接的名称
  • client_pause(self, timeout):在指定时间内终止运行来自客户端的命令(毫秒)
  • client_unblock(self, client_id, error=False):解除指定连接id的客户端阻塞
  • config_get, config_set,config_rewrite:读写redis.conf配置文件
  • config_resetstat(self):重置 INFO 命令中的某些统计数据
  • dbsize(self):返回当前数据库的 key 的数量
  • debug_object(self, key):获取 key 的调试信息
  • echo(self, value):打印字符串
  • flushall(self, asynchronous=False):清空所有数据库
  • flushdb(self, asynchronous=False):清空当前数据库
  • info(self, section=None):获取 Redis 服务器的各种信息和统计数值
  • lastsave(self):返回最近一次 Redis 成功将数据保存到磁盘上的时间,以 UNIX 时间戳格式表示

save(self):同步保存数据到硬盘

  • ping(self):查看服务是否运行
  • migrate(self, host, port, keys, destination_db, timeout,copy=False, replace=False, auth=None): 数据库迁移
  • shutdown(self, save=False, nosave=False):异步保存数据到硬盘,并关闭服务器
  • slaveof(self, host=None, port=None):将当前服务器转变为指定服务器的从属服务器(slave server)
  • slowlog_get(self, num=None):管理 redis 的慢日志
  • wait(self, num_replicas, timeout):Redis同步复制

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 如何原位删除python字典的key简单示例

    如何原位删除python字典的key简单示例

    这篇文章主要介绍了如何原位删除python字典的key的相关资料,为了避免在遍历字典时修改其结构导致的运行时错误,可以使用list(dic.items())创建键的副本,然后遍历这个副本进行删除操作,需要的朋友可以参考下
    2025-05-05
  • Python自动化操控鼠标的零基础完全指南

    Python自动化操控鼠标的零基础完全指南

    在日常的电脑使用中,我们经常会遇到大量重复性的鼠标操作,通过使用 Python 脚本,你可以让电脑自动、精准地移动鼠标、执行点击甚至滚动页面,本篇指南将带你从零开始,系统地学习如何使用 Python 操控你的鼠标,开启桌面自动化的第一步
    2026-04-04
  • 使用Python实现屏幕截图的两种方法

    使用Python实现屏幕截图的两种方法

    Python作为一种高效的编程语言,可以通过一些库来实现对屏幕的截图操作,本文主要介绍了使用Python实现屏幕截图的两种方法,具有一定的 参考价值,感兴趣的可以了解一下
    2023-12-12
  • Python 实现自动完成A4标签排版打印功能

    Python 实现自动完成A4标签排版打印功能

    这篇文章主要介绍了Python 实现自动完成A4标签排版打印功能,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-04-04
  • python中selenium操作下拉滚动条的几种方法汇总

    python中selenium操作下拉滚动条的几种方法汇总

    这篇文章主要介绍了python中selenium操作下拉滚动条的几种方法汇总,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-07-07
  • python中自定义with的具体使用

    python中自定义with的具体使用

    在 Python 中,with 语句用于简化资源管理,它保证在执行完代码块后正确地释放资源,通过__enter__和__exit__魔术方法实现,本文就来详细的介绍一下,感兴趣的可以了解一下
    2024-09-09
  • Python使用tkinter编写一个高效倒计时番茄钟

    Python使用tkinter编写一个高效倒计时番茄钟

    这篇文章主要为大家详细介绍了如何使用Python的tkinter库实现一个可视化番茄钟,包含倒计时显示以及工作,休息状态切换等功能,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下
    2026-01-01
  • 使用python实现读取文件夹中所有excel

    使用python实现读取文件夹中所有excel

    相信很多坐在办公室上班的朋友每天都需要处理大量的数据,本文我们就来看看如何使用Openpyxl读取文件夹下所有Excel文档中的数据,文中示例代码讲解详细,感兴趣的小伙伴可以了解下
    2025-12-12
  • 使用Python对Dicom文件进行读取与写入的实现

    使用Python对Dicom文件进行读取与写入的实现

    这篇文章主要介绍了使用Python对Dicom文件进行读取与写入的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-04-04
  • Python打印异常信息的方法示例详解

    Python打印异常信息的方法示例详解

    在 Python 编程中,异常是指程序执行过程中出现的错误或异常情况,当程序遇到异常时,为了更好地调试和定位问题,我们需要打印异常信息,本文将详细介绍如何在 Python 中打印异常,并提供一些示例和注意事项,需要的朋友可以参考下
    2023-12-12

最新评论