求助:被 python 的编码搞疯了 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
lovebeyondalways
V2EX    Python

求助:被 python 的编码搞疯了

  •  
  •   lovebeyondalways
    piaokorg 2016-06-04 11:15:44 +08:00 10208 次点击
    这是一个创建于 3449 天前的主题,其中的信息可能已经有所发展或是发生改变。

    小弟用的是 python3.5 ,听说 python3 解决了编码问题
    然而
    import urllib.request
    html = urllib.request.urlopen('http://www.baidu.com').read().decode('utf-8')
    print(html)

    结果:
    Traceback (most recent call last):
    File ".\Desktop\work\wearther.py", line 3, in <module>
    print(html)
    UnicodeEncodeError: 'gbk' codec can't encode character '\xbb' in position 25395: illegal multibyte sequence

    这样也不行.decode('utf-8').encode('utf-8')
    所以新手求助啊

    45 条回复    2016-06-07 11:36:45 +08:00
    276562578
        1
    276562578  
       2016-06-04 11:19:46 +08:00
    先看看是什么格式的编码,用 chardet 库,然后再 de 和 en
    GPU
        2
    GPU  
       2016-06-04 11:24:33 +08:00
    不是应该用 requests 吗?

    腰不酸腿不疼
    SuperMild
        3
    SuperMild  
       2016-06-04 11:24:34 +08:00
    可能是 Windows 的坑
    janxin
        4
    janxin  
       2016-06-04 11:28:59 +08:00
    试了一下没有问题啊,你这是 Windows 的坑吧
    a412739861
        5
    a412739861  
       2016-06-04 11:29:56 +08:00
    我用 requests 似乎需要设置这个的,直接能够打开 gbk 的。
    只是在 post 数据的时候,要 encode 成对应的编码,这个地方要自己写。
    lovebeyondalways
        6
    lovebeyondalways  
    OP
       2016-06-04 11:29:59 +08:00
    @janxin 我靠 windows 这坑怎么跳过
    Sylv
        7
    Sylv  
       2016-06-04 11:29:59 +08:00 via iPhone   1
    Python 3 的字符串已经是 unicode 了,你为什么还要 decode ?
    基础知识:
    unicode.encode(encoding) -> bytes
    bytes.decode(encoding) -> unicode
    unicode.decode(encoding) -> unicode.encode(defaultencoding).decode(encoding) -> unicode

    Python 3 是解决了部分 Python 2 的编码坑,但并不代表不再需要掌握基础的编码知识了。
    uniquecolesmith
        8
    uniquecolesmith  
       2016-06-04 11:42:19 +08:00   3
    你对编码的理解反了, unicode 是字符集,是规范,而 utf-8 是 unicode 的一种实现。或者你可以理解为 unicode 是非可视编码,而 utf-8 是可视编码,所以应该是个 encode('utf-8')才可行
    annielong
        9
    annielong  
       2016-06-04 11:43:00 +08:00
    大坑, windows+中文,回回都要被编码坑一下,
    uniquecolesmith
        10
    uniquecolesmith  
       2016-06-04 11:47:42 +08:00   1
    补充 没记错的话, windows 下应该 urllib.request.urlopen('http://www.baidu.com').read().encode('cp936')或者其他
    xiandao7997
        11
    xiandao7997  
       2016-06-04 11:51:04 +08:00
    @lovebeyondalways 在 iV2 结果基本上就是劝你换 mac :)
    以前也遇到这个坑,跟别人回复的一样,数据获取到了用 chardet 先检测一下编码,然后再 decode/encode, win 命令行里输出的话 utf8 貌似是不行的,只可以用 unicode//gbk/cp936 ,记不清了,你可以再试试~
    congeec
        12
    congeec  
       2016-06-04 12:02:28 +08:00
    不是 Python 坑你,是 Terminal 坑你。你的代码我在 OS X 下执行就没问题。 Windows ,如果我没记错的话,用 UCS-2/GBK 处理中文。你的 Terminal (应该是 cmd.exe 吧)有没有用 UTF-8 ?
    Delbert
        13
    Delbert  
       2016-06-04 12:09:35 +08:00 via Android
    win 的 cmd 是 cp936 , unicode 是 65001(印象中是这个)
    YuJianrong
        14
    YuJianrong  
       2016-06-04 12:10:42 +08:00 via iPad   3
    这个原因很容易理解吧?主要有两点
    1. GBK 没有完全覆盖 unicode ,有些 unicode 字符无法编码成 GBK
    2. windows 版本的 print 在中文 windows 环境下输出需要编译成环境编码也就是 cp936 , python 视 cp936 等同 GBK (这也没错)

    所以其实是 print 的锅,你不如把字符串编码成 utf8 存文件来看好了,不要 print 。
    21grams
        15
    21grams  
       2016-06-04 12:15:05 +08:00
    我用的还是 2.7 , 更痛苦,尤其在 windows 下,简直噩梦。
    cosven
        16
    cosven  
       2016-06-04 12:44:03 +08:00   1
    @YuJianrong 正解

    看它报错的位置嘛,说的是第三行,而不是第二行的 decode 有错,而楼上许多人都在分析 decode('utf-8') 这句有错。显然没有抓住问题关键。

    windows cmd 下 print 会把字符串转换成 gbk 编码来输出,所以才会有 LZ 现在遇到的问题。

    >>> html.encode('gbk') # 说明 html 这个字符串中有些字符不能编码成 gbk
    UnicodeEncodeError: 'gbk' codec can't encode character '\xbb' in position 25395: illegal multibyte sequence

    *****所以, LZ 的问题,并不是单纯的不能输出中文的问题*****

    解决办法
    1. 如 YuJianrong 所说:把它输出到文件是一种办法
    2. 参考这篇博客,貌似可以输出到 cmd: http://blog.csdn.net/jim7424994/article/details/22675759

    ---------题外话(关于 cmd python3 输出中文)-------------------
    参考 http://www.crifan.com/python_3_x_auto_handle_string_encode_and_decode_to_and_from_unicode_then_output_to_cmd/ 这篇博客,对 windows 下 python3 输出中文的一些况作了测试。

    ----------------------------------------------------------------------------

    @Sylv urlopen('http://www.baidu.com').read() 之后的对象是 bytes ,不是字符串
    @uniquecolesmith bytes 对象应该 decode 成 utf-8 ,而不是 encode
    walleL
        17
    walleL  
       2016-06-04 13:25:02 +08:00
    做了一些测试,我来整理一下吧(我用的 python2.7)

    1. cOntent= urllib.request.urlopen('http://www.baidu.com').read() # 得到 bytes
    2. text = content.decode('utf8') # 得到 unicode(这里已确定 content 为 utf8 编码)
    3. print(text) # print 时 python 会根据当前 sys.stdout 的编码对 text 进行 encode, win 下 stdout 的编码是 gbk ,而有些 unicode 无法编码为 gbk ,所以报错

    解决方案:
    1. @cosven 的回复中提到的博客里的方法:改 sys.stdout 的编码
    2. 先 encode 为 gbk ,并指定 errors='replace' (当遇到不可编码字符时使用 ? 替换), 然后 print:
    print(text.encode('gbk', errors='replace')) #不推荐,无法解码的字符可能就成 ? 了
    3. 结合 1,2: print(text.encode('gp18030'))
    lovebeyondalways
        18
    lovebeyondalways  
    OP
       2016-06-04 13:25:47 +08:00
    @cosven
    @YuJianrong 感谢 确实是 print 的问题
    cosven
        19
    cosven  
       2016-06-04 13:27:21 +08:00
    事后又仔细阅读了 http://blog.csdn.net/jim7424994/article/details/22675759 这篇博文,它使用 GB18030 编码可以成功输出。

    所以我猜(手上并没有 windows ): print(html.encode('gb18030')) 应该是可以正常输出的

    参考: gbk 编码都多种: , GB18030, GBK https://www.zhihu.com/question/19677619
    daimoon
        20
    daimoon  
       2016-06-04 14:11:28 +08:00
    简单的办法,把 python 安装目录中的 site.py 里面的 del sys.setdefaultencoding ,替换为 sys.setdefaultencoding("utf-8").
    以后就没问题了。
    hard2reg
        21
    hard2reg  
       2016-06-04 14:34:13 +08:00
    请用 requests
    hard2reg
        22
    hard2reg  
       2016-06-04 14:37:43 +08:00
    你抓 QQ 空间更恶心,有些 emoji 表情也会导致错误。。。
    ayaseangle
        23
    ayaseangle  
       2016-06-04 14:40:04 +08:00
    这是 cmd 的坑。。。
    dofine
        24
    dofine  
       2016-06-04 15:09:12 +08:00
    print 和 cmd 都很坑~~
    vinceguo
        25
    vinceguo  
       2016-06-04 15:33:47 +08:00 via Android
    别改 defaultencoding 。
    here you go: bit.ly/unipain
    YUX
        26
    YUX  
    PRO
       2016-06-04 16:00:09 +08:00
    import sys
    import io
    sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')

    在 python3 前面加上这三行就没有编码问题了
    ioven
        27
    ioven  
       2016-06-04 18:13:46 +08:00
    win 的坑,而非 py 坑
    个人解决方法,使用 conemu[https://conemu.github.io],开启 unicode 支持,运行 lz 代码无压力
    weizhixiang
        29
    weizhixiang  
       2016-06-04 21:25:31 +08:00 via Android
    win 的坑,首行加入#ciding=utf-8
    weizhixiang
        30
    weizhixiang  
       2016-06-04 21:26:06 +08:00 via Android
    @weizhixiang coding
    noe132
        31
    noe132  
       2016-06-05 00:39:33 +08:00
    最新版本 Sublime 的 built in 的 python 的 build system 是这样写的
    {
    "shell_cmd": "python -u \"$file\"",
    "file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)",
    "selector": "source.python",

    "env": {"PYTHONIOENCODING": "utf-8"},

    "variants":
    [
    {
    "name": "Syntax Check",
    "shell_cmd": "python -m py_compile \"${file}\"",
    }
    ]
    }


    其中有个
    "env": {"PYTHONIOENCODING": "utf-8"},
    添加一个这个环境变量
    好像这样就不会出现 unicode 错误了
    youtoshell
        32
    youtoshell  
       2016-06-05 01:24:12 +08:00 via Android   1
    reload(sys)
    sys.setdefaultencoding('utf-8')
    Ciruelas
        33
    Ciruelas  
       2016-06-05 05:03:07 +08:00 via iPhone
    不知道你解决这个问题了没有,我前两天刚好碰到类似的问题。报这个错是因为控制台使用的是 gbk 编码,要么把控制台改成 utf8 编码,要么把输出内容 decode 以后再 encode 成 gbk
    binux
        34
    binux  
       2016-06-05 05:18:49 +08:00   2
    python 编码其实并不是坑, python2 也不是,只是觉得坑的人不理解编码是什么东西。 encode , decode 乱用,没有依据地胡乱指定编码。
    9hills
        35
    9hills  
       2016-06-05 08:35:35 +08:00
    同意 ls ,反对 reload(sys)

    Python 的编码并不难理解,你只要理解 Unicode , GBK , UTF-8 , encode , decode 的含义即可。如果你使用 Windows ,需要知道 windows 的代码页是什么, CP936 是啥
    lovebeyondalways
        36
    lovebeyondalways  
    OP
       2016-06-05 08:58:23 +08:00 via Android
    @9hills 我靠…一大早又有那么多 v 友帮忙,非常感谢,我把 cmd 改成 utf-8 可以运行,现在在补充 Unicode 知识
    kysida
        37
    kysida  
       2016-06-05 10:29:23 +08:00
    一般这种问题是编码问题,这类问题可以直接尝试着使用 utf-8 , unicode 确实很重要
    imn1
        38
    imn1  
       2016-06-05 10:33:27 +08:00
    看上去像是 win
    win 首先要明白一个问题: cmd 默认编码不是 utf-8 ,无论怎么改只要 py 和 cmd 编码不同,输出就一定会出错
    wwqgtxx
        39
    wwqgtxx  
       2016-06-05 10:58:33 +08:00
    win 下这样输出也能搞定所有问题
    print (((str(input))).encode('gbk', 'ignore').decode('gbk') )
    knarfeh
        40
    knarfeh  
       2016-06-05 14:45:35 +08:00
    授人以鱼不如授人以渔:
    &feature=youtu.be
    est
        41
    est  
       2016-06-05 15:02:29 +08:00   1
    py 没有编码问题。是各种环境自己把编码问题搞乱了。
    Arnie97
        42
    Arnie97  
       2016-06-06 10:00:07 +08:00 via Android
    @weizhixiang 根本不对,这句话是指定 py2 源码文件的编码,对于 py3 是废话,因为 py3 要求源码必须是 utf8 。
    dreamtrail
        43
    dreamtrail  
       2016-06-06 10:19:45 +08:00
    python 的编码很简单了,你要碰到 perl 的,那是真的会疯
    brucedone
        44
    brucedone  
       2016-06-06 12:41:48 +08:00
    很多人刚开始学 py2 的时候,一定会被编码搞的很疯,但凡肯花点时间了解编码和解码原理的话,都可以很轻松走进 python 的大门
    kaneg
        45
    kaneg  
       2016-06-07 11:36:45 +08:00
    编码问题不是单靠语言就能解决的, Java 设计之初就支持 unicode , 但是在 Java 中处理中文的坑,相信很多人肯定都踩过。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5236 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 29ms UTC 08:51 PVG 16:51 LAX 00:51 JFK 03:51
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86