UnicodeDecodeError&#58 &#39ascii&#39 codec can&#39t decode byte 0xe4 in position 0&#58ordinal not in

在学习【音乐推荐系统】项目,使用协同过滤基于网易云音乐数据构建模型并进行预测时,出现了一系列的报错,头秃,记录一下踩坑历程:

首先要构建训练集,如下:

import os
import pickle
from surprise import KNNBaseline, Reader
from surprise import Dataset
path = "D:/LenovoQMdownload/recommendation_system_codes/"

# 重建歌单id到歌单名的映射字典
id_name_dic = pickle.load(open( path+"popular_playlist.pkl","rb"))
print("加载歌单id到歌单名的映射字典完成...")
# 重建歌单名到歌单id的映射字典
name_id_dic = {}
for playlist_id in id_name_dic:
    name_id_dic[id_name_dic[playlist_id]] = playlist_id
print("加载歌单名到歌单id的映射字典完成...")

file_path = os.path.expanduser(path+"popular_music_suprise_format.txt")
# 指定文件格式
reader = Reader(line_format='user item rating timestamp', sep=',')
# 从文件读取数据
music_data = Dataset.load_from_file(file_path, reader=reader)
# 计算歌曲和歌曲之间的相似度
print("构建数据集...")
trainset = music_data.build_full_trainset()
#sim_options = {'name': 'pearson_baseline', 'user_based': False}

然后就报错了:
在这里插入图片描述
报错提示:UnicodeDecodeError: ‘ascii’ codec can’t decode byte 0xe4 in position 0: ordinal not in range(128)

看起来好像是字符有问题,也不懂,然后百度了很多,继续踩坑:

(1)踩坑一:按照网友说的,直接加了下面的代码块,继续报错:

import sys
reload(sys)
sys.setdefaultencoding('utf-8')

在这里插入图片描述
再查,才发现 Python 3 的 sys 库里面已经没有 setdefaultencoding() 函数了

  • Python 3 与 Python 2 有很大的区别,其中Python 3 系统默认使用的就是utf-8编码。
  • 所以,对于使用的是Python 3 的情况,就不需要sys.setdefaultencoding(“utf-8”)这段代码。

查的大部分的解决办法如下图所示(解决 NameError: name ‘reload’ is not defined 这个问题)
在这里插入图片描述
(2)踩坑二:因为我的Python版本是3.7.6,所以我开开心心的加上了下面的代码:

from importlib import reload
reload(sys)

运行,依旧报错,又回到最开始的问题:
在这里插入图片描述
(3)踩坑三:实在是不知道哪里有问题了,就瞎改,把open给删了,写成了这样:

id_name_dic = pickle.load(path+"popular_playlist.pkl")

原来是这样:

id_name_dic = pickle.load(open(path+"popular_playlist.pkl","rb"))

在这里插入图片描述
这个报错我也是服了,也不知道是什么意思,百度了之后,发现人家是有open函数的,只不过多加了""才会出错,我这不知道啥玩意,大家可以看看别人的:
在这里插入图片描述
(4)踩坑四:无奈求助了大哥,他说让我改成这样试试:

id_name_dic = pickle.load(open(path+"popular_playlist.pkl","r", encoding = 'utf-8'))

然后又报错:
在这里插入图片描述
报错提示:TypeError: a bytes-like object is required, not 'str’

是由于 Python3和Python2的字符串兼容问题,因为数据文件是在Python2下序列化的,所以使用Python3读取时,需要将‘str’转化为’bytes’。

我学着网上加了重新序列化的代码(别人博主成功了,我还是错的T_T):

class StrToBytes:  
    def __init__(self, fileobj):  
        self.fileobj = fileobj  
    def read(self, size):  
        return self.fileobj.read(size).encode()  
    def readline(self, size=-1):  
        return self.fileobj.readline(size).encode()

# 重建歌单id到歌单名的映射字典
id_name_dic = pickle.load(StrToBytes(open(path + "popular_playlist.pkl", "r", encoding='utf-8')))

不开心呀,还是错,又回到了原点,还是最开始的问题:
在这里插入图片描述

解决方案

好,踩了一堆坑,熄火了,最后还是大哥发现了问题所在,直接写成下面这样即可:

id_name_dic = pickle.load(open(path + "popular_playlist.pkl", "rb"),encoding='bytes')

先来看看官方文档怎么说:

模块 pickle 实现了对一个 Python 对象结构的二进制序列化和反序列化。

“Pickling” 是将 Python对象及其所拥有的层次结构转化为一个字节流的过程,而 “unpickling” 是相反的操作,会将(来自一个 binary file 或者 bytes-like object 的)字节流转化回一个对象层次结构。Pickling(和 unpickling)也被称为“序列化”, “编组” 或者 “平面化”。而为了避免混乱,此处采用术语 “pickling” 和 “unpickling”。

在这里插入图片描述
原因是这样的:
在这里插入图片描述
之前的 pkl 应该是Python2直接存的,或者是Python3转成 bytes 格式存的;然后 open选择rb模式,相当于直接读取bytes到内存,但是 load的默认编码是 ascii相当于又把 bytes 转成了 ascii(不出错才怪)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值