V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
推荐学习书目
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
vJianZhen
V2EX  ›  Python

被编码问题搞炸了!

  •  
  •   vJianZhen · Apr 18, 2016 · 9173 views
    This topic created in 3673 days ago, the information mentioned may be changed or developed.

    http://i3.piimg.com/d031ecea9295bc8c.png

    做毕业设计,目前跟着《 Flask Web 开发》敲代码。 到了数据库这段,进行不下去了,因为编码问题。 文件的编码、连接编码、数据库编码、校验编码……不明所以,一团混乱。 图上的虽然是个警告,但是不消灭没法下一步。 网上找了一圈,还是没有方案能解决。 有大神知道怎么解决吗?还请不吝赐教~万分感谢!

    74 replies    2016-05-10 14:47:48 +08:00
    florije
        1
    florije  
       Apr 18, 2016   ❤️ 1
    扔到 git 上或者啥地方,帮你看下。
    neoblackcap
        2
    neoblackcap  
       Apr 18, 2016
    大致推测就是你建的表的默认值跟该字段的类型不符

    建议你将数据库类型,你的 Model 都放出来。同时提问的时候请参考, http://zhuanlan.zhihu.com/p/20752519
    gssdromen
        3
    gssdromen  
       Apr 18, 2016
    把出问题的地方代码贴一下看看呗
    viease
        4
    viease  
       Apr 18, 2016
    show 你的 git
    vJianZhen
        5
    vJianZhen  
    OP
       Apr 18, 2016
    各位,在百度云 http://pan.baidu.com/s/1o8Ijnce 看吧……
    尝试了很久,还是没能 push 上 github 。
    出错的地方大概在 hello.py 的第 69 行,查询数据库那行。
    vJianZhen
        6
    vJianZhen  
    OP
       Apr 18, 2016
    代码在此处
    https://gist.github.com/mafanshu/4d557b6ff32049fe59f202d9c8231770
    这个功能刚才才知道……@neoblackcap
    mornlight
        7
    mornlight  
       Apr 18, 2016
    user = User(username=form.name.data)

    你 debug 一下 form.name.data 是个什么东西,啥类型
    kaneg
        8
    kaneg  
       Apr 18, 2016
    你的 python 文件中有中文,应该在文件第一行加 encoding 声明:
    #encoding=utf-8
    haozhang
        9
    haozhang  
       Apr 18, 2016 via iPhone
    三码合一: python 代码文件编码, mysql 连接时的编码, mysql 数据库存储的编码
    vJianZhen
        10
    vJianZhen  
    OP
       Apr 18, 2016
    @mornlight 是从表单里获得的文本框里的数据,字符串类型
    @kaneg 声明后没变化
    vJianZhen
        11
    vJianZhen  
    OP
       Apr 18, 2016
    @haozhang Python 代码文件编码 utf-8 , MySQL 中 character_set_connection 值为 utf-8 , character_set_database 值为 utf8mb4 (原本是 utf8 ,后来根据网上的说法改成这样,都没用)
    vJianZhen
        12
    vJianZhen  
    OP
       Apr 18, 2016
    另外,在浏览器上报的是 500 错误。书本对应的项目地址: https://github.com/miguelgrinberg/flasky
    Vamwere
        13
    Vamwere  
       Apr 18, 2016
    这个时候是不是应该说一句请用 python3 ?
    loading
        14
    loading  
       Apr 18, 2016
    如果使用 py2 ,请在所有字符串前面加上 u ,也就是:

    u'sadfsa'

    多用 decode,encode
    vJianZhen
        15
    vJianZhen  
    OP
       Apr 18, 2016
    @Vamwere 用的就是 Python3.5.32 ,但我觉得也有版本不匹配的因素才导致了问题。=
    vJianZhen
        16
    vJianZhen  
    OP
       Apr 18, 2016
    Python 的版本是 3.5.1 。
    hahastudio
        17
    hahastudio  
       Apr 18, 2016
    >>> print "\xD6\xD0\xB9\xFA\xB1\xEA".decode("gbk")
    中国标
    你有地方存的数据是 GBK 编码的

    Python 别老跟 Windows 一起用= =
    vJianZhen
        18
    vJianZhen  
    OP
       Apr 18, 2016
    @hahastudio 所有能想到的地方都是 utf8 编码的,实在不知道哪里有数据是 gbk 编码。==。用 Windows 是因为习惯,慢慢会转 Linux 或 MAC
    florije
        19
    florije  
       Apr 18, 2016
    好吧,本地全 utf-8 环境 db.create_all()是没有任何问题的。
    form.name.data 这个的编码是 GBK ,搜下 mysql 相关的就能找到这个错误。
    vJianZhen
        20
    vJianZhen  
    OP
       Apr 18, 2016
    而且没有『中国标』这三个字的数据,我不知道它从哪里冒出来的==。难道是 PyMySQL 的行为么?
    dphdjy
        21
    dphdjy  
       Apr 18, 2016 via Android   ❤️ 2
    国标是习惯简称。。。
    GBK 国标扩
    florije
        22
    florije  
       Apr 18, 2016
    如果没猜错肯定有一个地方用到了%z 的,类似 time.strftime('%z'),也就是会输出中国标准时间。
    vJianZhen
        23
    vJianZhen  
    OP
       Apr 18, 2016
    form.name.data 这个字段是从网页上请求上来的,我查看了页面的编码也是 utf8 的。"\xD6\xD0\xB9\xFA\xB1\xEA"根据 gbk 编码解码后是『中国标』三个字,但是这三个字我们提交过,况且我提交的都是英文。页面的效果如图: http://i2.piimg.com/9c238b4453491952.png
    vJianZhen
        24
    vJianZhen  
    OP
       Apr 18, 2016
    @florije 目前在数据库方面没有涉及时间,除非是 PyMySQL/MySQL 等自己的行为。目前数据库上面只有两个表,列也是非常简单的字段。涉及到时间的在前端用了 Flask-Moment ,但是诚如效果图所示,是用英文显示的。
    pixstone
        25
    pixstone  
       Apr 18, 2016
    http://nedbatchelder.com/text/unipain.html
    看篇,很好的解释了编码问题。
    vJianZhen
        26
    vJianZhen  
    OP
       Apr 18, 2016
    @pixstone 但是……英文的,篇幅有点长,怕来不及消化。现在只想快点把问题解决掉。
    est
        27
    est  
       Apr 18, 2016
    py2, windows, gbk ,三码合一就直接把新手炸毛了
    vJianZhen
        28
    vJianZhen  
    OP
       Apr 18, 2016
    @est 对,我实在要哭了!
    Tink
        29
    Tink  
    PRO
       Apr 18, 2016 via iPhone
    为啥用 windows 呢
    neoblackcap
        30
    neoblackcap  
       Apr 18, 2016
    已经在 linux 下面实现过一次,像你截图一样调用 create_all 方法并不会报错。

    估计还是你页面上收集到的数据没有做校验转码而产生的错误
    vJianZhen
        31
    vJianZhen  
    OP
       Apr 18, 2016
    @Tink 因为对 Linux 平台不熟悉,出了问题更懵逼
    vJianZhen
        32
    vJianZhen  
    OP
       Apr 18, 2016
    @neoblackcap 首先谢谢你。不知道你实现时版本一样吗?我现在很怀疑是版本的 bug 或者是隐藏很深的问题。从页面上只收集了一个『 username 』,提交的还是『 Kobe 』……通过命令行能打印出来。
    hahastudio
        33
    hahastudio  
       Apr 18, 2016
    http://blog.wifibao.im/index.php/archives/158/
    是不是新手都有这问题

    https://stackoverflow.com/questions/2108824/mysql-incorrect-string-value-error-when-save-unicode-string-in-django
    columns can have their own character sets, independent of the tables and the database.
    neoblackcap
        34
    neoblackcap  
       Apr 18, 2016
    @vJianZhen
    python 是 3.5.0, 各类包如下
    dominate (2.2.0)
    Flask (0.10.1)
    Flask-Bootstrap (3.3.5.7)
    Flask-Moment (0.5.1)
    Flask-Script (2.0.5)
    Flask-SQLAlchemy (2.1)
    Flask-WTF (0.12)
    itsdangerous (0.24)
    Jinja2 (2.8)
    MarkupSafe (0.23)
    pip (7.1.2)
    PyMySQL (0.7.2)
    setuptools (18.2)
    SQLAlchemy (1.0.12)
    visitor (0.1.2)
    Werkzeug (0.11.8)
    WTForms (2.1)

    至于 MySQL 也是使用 5.7 了
    vJianZhen
        35
    vJianZhen  
    OP
       Apr 18, 2016
    @hahastudio 列也有字符集确实是个新观念。问题是,在视图函数上通过 create_all()来创建表的时候问题就出现了,根本不涉及插入。
    vJianZhen
        36
    vJianZhen  
    OP
       Apr 18, 2016
    @neoblackcap 版本几乎都一样。我就更懵逼了……
    pixstone
        37
    pixstone  
       Apr 18, 2016
    @loading 已经不建议 用 u “中文” 这种形式了,推荐: from __future__ import unicode_literals ,配合 # coding=utf-8


    然后 还有一个 歪招:

    if "的" in text: 这个(之前 V2 的帖子看到)
    guyskk
        38
    guyskk  
       Apr 18, 2016
    如果还没解决的话, pdb 调试
    http://python.jobbole.com/81184/
    feng32
        39
    feng32  
       Apr 18, 2016
    用全英文就行了, UI 看起来更专业,而且别人还不知道你是为了避免处理编码问题
    windfarer
        40
    windfarer  
       Apr 18, 2016 via Android
    Python3 一劳永逸
    loading
        41
    loading  
       Apr 18, 2016 via Android
    @pixstone 用过,有坑!
    loading
        42
    loading  
       Apr 18, 2016 via Android
    个人建议,楼主直接上 py3 ,目测楼主还没写几行!
    zhuangzhuang1988
        43
    zhuangzhuang1988  
       Apr 18, 2016
    pycharm 一行行调试。。
    imkh
        44
    imkh  
       Apr 18, 2016 via iPhone   ❤️ 1
    笑了,一群说用 Python 3 的都眼瞎了吧?也不看楼主的补充说明
    cxbig
        45
    cxbig  
       Apr 18, 2016
    换 Linux 或 Mac OS 来开发吧
    loading
        46
    loading  
       Apr 18, 2016 via Android
    看来 py3 也是醉人…
    vJianZhen
        47
    vJianZhen  
    OP
       Apr 18, 2016
    @cxbig 时间紧,别的平台也不熟悉
    vJianZhen
        48
    vJianZhen  
    OP
       Apr 18, 2016
    @feng32 全是中文,也出问题
    WangYanjie
        49
    WangYanjie  
       Apr 18, 2016
    @kaneg 中文应该是作者后来加的
    florije
        50
    florije  
       Apr 18, 2016
    user = User.query.filter_by(usrname=form.name.data).first()
    唉,楼主能跟我说下 usrname 是什么吗?
    florije
        51
    florije  
       Apr 18, 2016
    虽然很喜欢 LZ 的钻研精神,但是还是建议刚刚接触新知识还是用点只能的 IDE 比较靠谱。
    florije
        52
    florije  
       Apr 18, 2016   ❤️ 1
    真心没必要开系统炮,然后发现家里电脑也有类似 lz 的 warning ,但是公司的没有,稍后我看看是哪里提示的,貌似是 sqlalchemy 抛出的。
    Kilerd
        53
    Kilerd  
       Apr 18, 2016
    只能说玩不来 编码,就乖乖的去 用 Python3 吧。
    florije
        54
    florije  
       Apr 18, 2016   ❤️ 1
    @Kilerd 能别开编码炮了么……上面已经找到问题了。

    @vJianZhen 找到了,额, sqlalchemy 问题,在 win 下需要调整下“更改系统区域设置”属性(具体位置百度)为英语(美国)搞定。
    vJianZhen
        55
    vJianZhen  
    OP
       Apr 18, 2016
    @florije 开始用着 PyCharm 的,用着用着觉得很多事它帮我做了,这样对理解没帮助。现在正在试你的方法了……
    florije
        56
    florije  
       Apr 18, 2016   ❤️ 1
    @vJianZhen 额,我的意思是你代码有问题, User 类里面的 username 属性你拼写错成 usrname 了,然后一般的我推荐用 filter 方法,直接用类.属性,不容易出错,至于 pycharm 看你怎么用了,格式化下了,看下代码有没问题了之类的完全可以用嘛。
    vJianZhen
        57
    vJianZhen  
    OP
       Apr 18, 2016
    @florije 你……你你你,我……我我……问题被你解决了!把拼写写对了,也更改了系统设置,运行 OK 了。太谢谢。
    jwk345
        58
    jwk345  
       Apr 18, 2016
    cmd 的问题?如果你 Windows 是中文的,默认终端就是 GBK
    vJianZhen
        59
    vJianZhen  
    OP
       Apr 18, 2016
    @florije 现在是这样,把拼写写好,能运行起来,虽然有警告;如果再把“更改系统区域设置”为英语(美国),既不出警告,也能正常运行。问题已经解决了。那请问你知道为什么吗?就是原理上的东西。
    hahastudio
        60
    hahastudio  
       Apr 18, 2016 via Android
    @vJianZhen cmd 的编码从 CP936 变成 CP1252 了?
    glasslion
        61
    glasslion  
       Apr 19, 2016
    @vJianZhen 分别在 Linux/Mac 和 Windows 下运行下面的代码, Linux 下这几个 encoding 全部是 utf8 而 windows 则是千奇百怪



    ```
    import sys, locale

    expressions = """
    locale.getpreferredencoding()
    type(my_file)
    my_file.encoding
    sys.stdout.isatty()
    sys.stdout.encoding
    sys.stdin.isatty()
    sys.stdin.encoding
    sys.stderr.isatty()
    sys.stderr.encoding
    sys.getdefaultencoding()
    sys.getfilesystemencoding()
    """

    my_file = open('dummy', 'w')

    for expression in expressions.split():
    value = eval(expression)
    print(expression.rjust(30), '->', repr(value))

    ```

    Python 和 encoding 1 相关的配置主要有下面几个:
    1. ` locale.getpreferredencoding()` 这个用的是最广的。 这是 Python 在 open 文件时默认使用的 encoding
    2. `sys.getdefaultencoding() ` 是 Python 进行 str/unicode(byte/str) 转换时默认使用的 encoding
    3. `sys.getfilesystemencoding()` 是用来 encoding 文件**名**的, 例如 open(b'balabala')
    4. 标准输入输出(print)的 encoding:
    4.1 若设置了 `PYTHONIOENCODING` 环境变量, 则以次变量为准
    4.2 标准输入输出是打到终端的话, 看终端的 locale 配置, 在 windows cmd 的代码页
    4.3 标准输入输出被重定向到文件的话, 则参照 1 , 用的是 ` locale.getpreferredencoding()`

    @hahastudio
    @hahastudio
    vJianZhen
        62
    vJianZhen  
    OP
       Apr 19, 2016 via iPad
    @hahastudio 没有。这个警告可以通过更改系统区域设置来消除。另外,我把 username 拼写成 usrname 了,否则有警告也可以运行出来的。我很自责。
    ibigbug
        63
    ibigbug  
       Apr 19, 2016
    @pixstone 的 in text 这个是什么魔法
    ipconfiger
        64
    ipconfiger  
       Apr 19, 2016
    自从弃了瘟到死就很少遇到编码问题了
    picasso250
        65
    picasso250  
       Apr 19, 2016
    每次别人遇到编码问题,我都建议他换 PHP 。
    但是没有一次别人认为我是真诚的。
    jugelizi
        66
    jugelizi  
       Apr 19, 2016
    哈哈
    曾经在 win 下坑死
    一段小代码 py2.7 运行没有任何报错就是没返回 扔到 linux 下很快结果出来了
    zjj2008se
        67
    zjj2008se  
       Apr 19, 2016 via Android
    win 下面的编码一泡污,就算 py3 还是会 gbk 报错,除了改区域没别的办法。
    pynix
        68
    pynix  
       Apr 19, 2016 via Android
    主要问题就是在 Windows 下折腾。。
    XiMing
        69
    XiMing  
       Apr 19, 2016
    收藏一波,感觉我也会遇到。
    RockShake
        70
    RockShake  
       Apr 19, 2016
    看到问题解决了还是很开心的,很多人根本不看问题和用的版本,乱说一通,给 @florije 赞一个
    zonghua
        71
    zonghua  
       Apr 20, 2016 via iPhone
    困扰了我许久,文件下载的时候怎么用中文命名?试过多钟方法均无效
    TGlivecoding
        72
    TGlivecoding  
       Apr 23, 2016
    如果是 3 的话我用 3 实现过一遍这本书代码: https://github.com/taogeT/flask_web_development_python3 ,不知道对你有没有帮助?
    florije
        73
    florije  
       May 10, 2016   ❤️ 1
    @vJianZhen 其实问题在 mysql 上面,如果没猜错,你用的 mysql 是 5.7.*的,貌似里面验证什么地方编码的东西了。换上 5.6.*就没有这个提示了,当然上面系统编码修改那个算是临时的方案吧。
    vJianZhen
        74
    vJianZhen  
    OP
       May 10, 2016
    @florije 确实是 5.7
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   1162 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 102ms · UTC 17:59 · PVG 01:59 · LAX 10:59 · JFK 13:59
    ♥ Do have faith in what you're doing.