• Python入门第10篇(编码)


    目录

    一、编码是什么?

    二、Python中编码

    1.读取文件引发的问题

    2.其实是Windows的问题

    3.试着改改问题

    4.各种骚操作

    5.终极解决

    6.推荐方案

    总结

    Python系列文章目录


    前言

    编码存在于所有文件,比较常见的ASCII、utf8、gbk等。最常用的还是utf8编码。

    在编码领域,也会涉及到代码文件,那么也会涉及编码问题,今天就这一问题进行介绍。

    一、编码是什么?

    编码就是特定字符的集合,是用于显示特点的字符。比如ASCII只能显示256个字符,utf8则可以表示各种符号多种语言的文字,具有更好的包容性。

    二、Python中编码

    1.读取文件引发的问题

    一般读取文件内容,我们这么写代码就可以了

    1. with open("./.env", "r",encoding="utf-8") as f:
    2. print(f.read())

    如上代码,是直接读取环境变量文件,并且设置了编码为utf8,这里如果编码不匹配,就会报错:

    UnicodeDecodeError: 'gbk' codec can't decode byte 0x95 in position 8: illegal multibyte sequence

    因为读取文件内容的时候,有些中文在不同编码格式下编码信息是不一样的,就会导致报错。

    由于一般用的都是utf8编码,那我们平时都用utf8编码,这种出错的情况也会很少。

    但是随着Python开发接触的越来越多,你一定会用到很多其他的包,这个时候可能就会出意外了。比如某个包提供一个读取配置文件的方法,你感觉应该没问题,结果执行的时候就报错了,然后翻到包里的代码去看,结果,我的天,它咋不设置编码格式!!!

    1. with open(str(template_file), "r") as f:
    2. template = f.read()

    一开始我就直接把人家包的代码给改了,加了encoding参数,问题暂时是解决了,但是会后患无穷,包不得更新,一个更新又出问题了,你如果都忘了这事,那真是神不知鬼不觉的。 

    2.其实是Windows的问题

    经过一系列了解,原来这个问题主要出在Windows系统。自从Python3开始,Python的默认编码就是utf8了,这个在Linux、Mac系统下都没问题的。唯独在Windows下有问题,简单说在Windows下Python获取当前编码,还和操作系统编码、区域啥的有关系了

    3.试着改改问题

    读取文件其实是一个解码的过程,根据提示通过gbk无法解码某个字符,说明当前读取文件用的是gbk编码,但是gbk解码出错,说明读取的文件编码不是gbk,看了下文件编码确实不是gbk,而是utf8。为啥会这样,一会我们说。我们先看咋解决

    结合如上分析,一个办法就是我们把文件编码也改为gbk,应该就可以了呗。改了果然可以。

    就当我以为要大功告成的时候,突然想起来,Linux一直没这种编码问题的,于是决定用相同代码和相同的文件(修改编码为gbk)在Linux环境测试。

    哇咔咔,果断报错。UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb2 in position 0: invalid start byte

    通过上面的分析经验,我们知道Linux默认是用的utf8解码,但是我们的文件却改为了gbk编码,那不报错才怪呢

    看来,我这个改法是不行的,不能Windows改好了,结果Linux废了。

    还得找路子


    这里顺便说下Windows下为啥文件编码默认就是utf8,但是默认解码却是gbk。

    文件是我们新建的,和Python本身是没关系的,而文件新建其实我们一般在开发环境下操作,比如我用的就是VSCode,这些开发工具其实默认编码已经设置为了utf8,这也就是为啥文件编码默认是utf8的原因。

    而解码是要Python代码来实现,而默认解码同样是Python底层控制的,开发环境在python底层之上,是无法反向干预的。而默认解码在Windows下和操作系统编码、区域(或根据操作系统语言匹配一个编码,gbk就是我们国家的编码)相关的。


    4.各种骚操作

    问题没解决,只能各种问AI、问度娘了

    1)设置PYTHONIOENCODING环境变量————————————没卵用

    2)locale.setlocale(locale.LC_ALL, ".UTF-8")——————————没卵用

    3)_locale._getdefaultlocale = (lambda *args: ['en_US', 'utf8'])——没卵用

    1. default_encoding = locale.getpreferredencoding()
    2. print("当前环境的默认编码是:", default_encoding)

    如上代码可以查看当前环境的默认编码,但是经过如上设置,这个默认编码还是cp936,其实就是gbk,cp936是Windows操作系统内部编码叫法,可见很大概率和操作系统有关系

    4)sys.setdefaultencoding('utf-8')——————————————没卵用,还报错

    这玩意其实是Python2中才有的,Python3默认编码就是utf8,这玩意取消了,所以在搜索信息的时候还要明确是Python3

    5)指定sys.flags.utf8_mode————————————————没卵用,还报错

    sys.flags.utf8_mode是只读属性无法设置

    5.终极解决

    好奇会害死猫

    好奇也会让我都不想去吃饭,不想出去遛弯,只为找到真理

    终于找到两个个靠谱的

    1)设置环境变量PYTHONUTF8=1

    测试no problem。

    2)重写open,从而给open加了encoding参数

    1. original_open = __builtins__.open
    2. def uopen(*args, **kwargs):
    3. if "b" not in (args[1] if len(args) >= 2 else kwargs.get("mode", "")):
    4. kwargs.setdefault("encoding", "UTF-8")
    5. return original_open(*args, **kwargs)
    6. __builtins__.open = uopen 如上代码干啥用的,使用了python的哪些技术点

    测试同样ok

    附上参考链接:1. 命令行和环境 — Python 3.12.3 文档icon-default.png?t=N7T8https://docs.python.org/3/using/cmdline.html#envvar-PYTHONUTF8

    3)命令行运行增加-X utf8参数

    运行py命令:python xx.py,注意是在python和xx.py之间增加

    完整命令:python -X utf8 xx.py

     测试可用,不过仅限于命令窗口,PyCharm中可以设置运行的时候增加这个脚本,不过我用的CSCode,参考链接:Python open 默认编码修改_python open utf8-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/linuxweiyh/article/details/124538216

    6.推荐方案

    如上5.终极解决,有几个方案可选,但是从通用性考虑,还是通过改环境变量的方式最省事。

    其他办法要不不通用,要不需要修改的代码比较多,比如重写open,涉及问题的代码文件都得加这个代码。

    改环境变量就没这个问题,反正Linux默认就是utf8,Windows和Linux、Mac统一了也没啥问题。

    总结

    通过一个小小的编码,引出一个Windows操作系统下Python编码的问题,网上相关资料很多,但是真正解决问题的资料却偏少,是不是多数Python开发用Linux、Mac操作系统。

    不管如何,总算解决问题了。


    Python系列文章目录

    Python入门第01篇(Python安装与开发工具)-CSDN博客

    Python入门第02篇(pip、字符串、方法、json、io操作)_python json pip-CSDN博客

    Python入门第03篇(异常处理、dotenv)_load_dotenv()-CSDN博客

    Python入门第04篇(sqlite数据库相关)_cmd中使用sqlite-CSDN博客

    Python入门第05篇(爬虫相关)-CSDN博客

    Python入门第06篇(FastApi、uvicorn)_fastapi uvicorn-CSDN博客

    Python入门第09篇(conda虚拟环境)-CSDN博客

    Flask开发webapi初步及过程问题探究_flask webapi-CSDN博客

    Linux下docker运行python_linux docker运行python-CSDN博客

  • 相关阅读:
    SQL题
    技术周总结 08.05-08.11周日(scala git回滚)
    STM32F030F4驱动TIM1637数码管芯片
    堡塔APP 免费使用教程【图文教程】
    JVM——运行时数据区(程序计数器+栈)
    手把手教你用C语言写出“走迷宫”小游戏(能看懂文字就会自己敲系列)
    HTTPS原理(证书验证+数据传输)
    gitlab搭建
    vue 将public文件下的图片引入.vue文件内
    vulnhub DOUBLETROUBLE: 1靶机
  • 原文地址:https://blog.csdn.net/ewqewqqwe/article/details/138194945