在Sublime Text 3上构建的Python 2.7不会打印' \ uFFFD'字符

时间:2017-10-20 20:08:00

标签: python python-2.7 unicode sublimetext3 stdout

问题。

我在Sublime Text 3上使用Python 2.7构建并且在打印时遇到问题 在某些情况下,我为'\uFFFD' - 'REPLACEMENT CHARACTER'输出了相当混乱的输出。

例如:

print u'\ufffd' # should be '�' - the 'REPLACEMENT CHARACTER'
print u'\u0061' # should be 'a'
-----------------------------------------------------
[Finished in 0.1s]

订单倒置后:

print u'\u0061' 
print u'\ufffd'
-----------------------------------------------------
a
�
[Finished in 0.1s]

因此,Sublime可以打印出'�'性格,但由于某种原因,在第一种情况下没有这样做 而输出对语句顺序的依赖似乎很奇怪。

替换字符的问题通常导致非常不可预测的打印输出行为 例如,我想打印出错误替换的解码字节:

cp1251_bytes = '\xe4\xe0' # 'да' in cp1251 
print cp1251_bytes.decode('utf-8', errors='replace')
-----------------------------------------------------
��
[Finished in 0.1s]

让我们替换字节:

cp1251_bytes = '\xed\xe5\xf2' # 'нет' in cp1251
print cp1251_bytes.decode('utf-8', errors='replace')
-----------------------------------------------------
[Finished in 0.1s]

再添加一个打印声明:

cp1251_bytes = '\xed\xe5\xf2' # 'нет' in cp1251 
print cp1251_bytes.decode('cp1251') 
print cp1251_bytes.decode('utf-8', errors='replace')
-----------------------------------------------------
нет
���
[Finished in 0.1s]

下面是一些其他测试用例的实现说明:

enter image description here

总结,所描述的打印输出行为有以下模式:

  • 它取决于print语句中偶数/奇数的'\ufffd'个字符
  • 这取决于打印语句的顺序
  • 这取决于具体的构建运行

    我的问题:

  • 为什么会这样?
  • 如何解决问题?


    我的Python 2.7 sublime-build文件:

    {   
        "cmd": ["C:\\_Anaconda3\\envs\\python27\\python", "-u", "$file"],
        "file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)",
        "selector": "source.python",
        "env": {"PYTHONIOENCODING": "utf-8"}
    }
    

    与Anaconda分开安装Python 2.7时,行为完全相同。

  • 2 个答案:

    答案 0 :(得分:1)

    编辑-1 - 使用带BOM的UTF8

    在Windows的情况下,似乎BOM变得很重要。所以你需要使用下面的类型构建配置

    {   
        "cmd": ["F:\\Python27-14\\python", "-u", "$file"],
        "file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)",
        "selector": "source.python",
        "env": {
            "PYTHONIOENCODING": "utf_8_sig"
        },
    }
    

    之后它也可以在Windows上正常使用

    build settings

    correct output

    原始答案

    我检查了这个问题,我在Python 2.7上使用Sublime文本时没有遇到同样的问题。唯一的变化是我必须将# -*- coding: utf-8 -*-添加到文件的顶部。这似乎是这个问题中缺失的部分

    # -*- coding: utf-8 -*-
    
    print u'\u0061' # should be 'a'
    print u'\ufffd' # should be '�' - the 'REPLACEMENT CHARACTER'
    

    之后,逆转没有影响

    print 1

    print 2

    您可以在

    上查看有关此必需标头的更多详细信息

    Why declare unicode by string in python?

    以下是上述链接的摘要

      

    当您指定# -*- coding: utf-8 -*-时,您告诉Python您保存的源文件是utf-8。 Python 2的默认值是ASCII(对于Python 3,它是utf-8)。这只会影响解释器读取文件中字符的方式。

    答案 1 :(得分:1)

    我已经重现了您的问题,我发现无论如何都能在我的平台上运行解决方案:-u构建配置选项中删除cmd标记。< / p>

    我不是百分之百确定为什么会这样,但是由于控制台解释了包含多字节字符的无缓冲数据流,这似乎是一种糟糕的交互。这是我发现的:

    • -u option将Python的输出切换为 unbuffered
    • 此问题与替换字符完全无关。我和其他人物如“あ”(U + 3042)也有类似的行为。
    • 其他编码也会发生类似的糟糕结果。设置"env": {"PYTHONIOENCODING": "utf-16be"}会导致print u'\u3042'输出0B

    将编码设置为UTF-16BE的最后一个示例说明了我的想法。控制台一次接收一个字节,因为输出是无缓冲的。所以它首先接收0x30字节。然后控制台确定这不是有效的UTF-16BE,而是决定回退到ASCII,从而输出0。它的课程接收后面的下一个字节,并遵循相同的逻辑输出B

    使用UTF-8编码,控制台接收的字节不可能被解释为ASCII,所以我相信控制台在正确解释无缓冲流方面做得稍微好一点,但它仍然遇到困难你的问题指出了。