0 开门见山
在文件开头加上如下代码即可【强行】修改encoding
import _bootlocale
_bootlocale.getpreferredencoding = lambda do_setlocale = True : "utf-8"
1 前言
当我们想使用utf-8编码打开一个json或其他文件的时候, 会使用:
import json
f = open('abc.json', 'r', encoding='utf-8')
j = json.load(f)
十分简单方便, 但是使用第三方COCO库时, 我们只能调用:
coco_api = COCO(json_file)
## 如下为COCO构造函数:
class COCO:
def __init__(self, annotation_file=None):
"""
Constructor of Microsoft COCO helper class for reading and visualizing annotations.
:param annotation_file (str): location of annotation file
:param image_folder (str): location to the folder that hosts images.
:return:
"""
# load dataset
self.dataset,self.anns,self.cats,self.imgs = dict(),dict(),dict(),dict()
self.imgToAnns, self.catToImgs = defaultdict(list), defaultdict(list)
if not annotation_file == None:
print('loading annotations into memory...')
tic = time.time()
with open(annotation_file, 'r') as f:
dataset = json.load(f)
其中的open是被写死的, 调用utf-8编码的文件就会报错:
<stderr>:UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 724090: ordinal not in range(128)
所以我们要通过一些方法修改open函数的默认打开方式
2 locale
2.1 其他的显示默认编码方法
笔者调研了众多显示默认/修改默认编码的方法, 有的博客说python3默认就是utf-8, 有的说:
PYTHONIOENCODING=utf-8 python abc.py
python -X utf-8 abc.py
import sys
print(sys.platform)
print(sys.getdefaultencoding())
import locale
print(locale.getpreferredencoding())
提供了四种方法, 而然前三种方法均无效, 使用过后还是会报
UnicodeDecodeError: 'ascii' codec can't decode byte 的错误
只有第四种, 会显示
encoding='ANSI_X3.4-1968'
让笔者找到了希望, 于是便从修改第四种方法的默认值改起:
2.2 locale概述
locale 是 Linux 系统中多语言环境的设置接口,在 Linux 中,使用 locale 命令来设置和显示程序运行的语言环境,locale 会根据计算机用户所使用的语言,所在国家或者地区,以及当地的文化传统定义一个软件运行时的语言环境。locale 由ANSI C提供支持。
这位兄弟写的很详细:
3 修改默认Encoding
既然
import locale
print(locale.getpreferredencoding())
返回值是ANSI_X3.4-1968, 我们便从getpreferredencoding() 函数下手
查看 locale.py源码编发便可发现, 其实是调用的 _bootlocale.getpreferredencoding() , 而且根据各个平台的不同自动构建;
且返回值也就是一个简单的string.
我们想想办法可以直接重写函数 "_bootlocale.getpreferredencoding", 让其无论如何返回值都为 "UTF-8"
还好python万物皆引用,
直接赋值一个小匿名函数即可:
import _bootlocale
_bootlocale.getpreferredencoding = lambda do_setlocale = True : "utf-8"
完美解决!