将 unicode 字符串编码为 utf-8 并获取问号

Encoding a unicode string to utf-8 and getting question marks

系统:

Python 2.7.5 , IPython 2.3.1 , OSX terminal (local), sys.stdout.encoding : 'UTF-8'
(venv) toz$ locale LANG="en_US.UTF-8" LC_COLLATE="en_US.UTF-8" LC_CTYPE="en_US.UTF-8" LC_MESSAGES="en_US.UTF-8" LC_MONETARY="en_US.UTF-8" LC_NUMERIC="en_US.UTF-8" LC_TIME="en_US.UTF-8" LC_ALL= –

我希望这两个命令打印相同,但后者打印 ord(c)>128 的问号。这是为什么?我如何编码这个 unicode 字符串并遍历而不得到问号?

In [77]: for c in u'!"#%\'()*+,-./:;<=>?@[\]^_`{|}~’”“': print c.encode('utf-8'),
! " # % ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~ ’ ” “

In [78]: for c in u'!"#%\'()*+,-./:;<=>?@[\]^_`{|}~’”“'.encode('utf-8'): print c,
! " # % ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~ ? ? ? ? ? ? ? ? ?

让我们打印 ord 值:

In [92]: for c in u'!"#%\'()*+,-./:;<=>?@[\]^_`{|}~’”“': print c.encode('utf-8'),ord(c),
! 33 " 34 # 35 % 37 ' 39 ( 40 ) 41 * 42 + 43 , 44 - 45 . 46 / 47 : 58 ; 59 < 60 = 61 > 62 ? 63 @ 64 [ 91 \ 92 ] 93 ^ 94 _ 95 ` 96 { 123 | 124 } 125 ~ 126 ’ 8217 ” 8221 “ 8220

In [93]: for c in u'!"#%\'()*+,-./:;<=>?@[\]^_`{|}~’”“': print c.encode('utf-8'),ord(c.encode('utf-8')),
! 33 " 34 # 35 % 37 ' 39 ( 40 ) 41 * 42 + 43 , 44 - 45 . 46 / 47 : 58 ; 59 < 60 = 61 > 62 ? 63 @ 64 [ 91 \ 92 ] 93 ^ 94 _ 95 ` 96 { 123 | 124 } 125 ~ 126 ’---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-93-1eb3985b825b> in <module>()
----> 1 for c in u'!"#%\'()*+,-./:;<=>?@[\]^_`{|}~’”“': print c.encode('utf-8'),ord(c.encode('utf-8')),

TypeError: ord() expected a character, but string of length 3 found

我可以将三到九个问号的长度与三个非 ASCII 字符中的每一个所需的(三个)字节联系起来。

您似乎有 "C" 语言环境。您可以使用 locale shell 命令进行检查。 或者你可以 运行 ipython 和 LANG=en_US.UTF-8 ipython (对于 bash/sh/etc)

当您 encode 一个字符串时,它会将 Unicode 字符转换为字节。每个字符都可以变成可变数量的字节。您的控制台似乎将 ASCII 范围 0-127 之外的任何字节打印为问号。

>>> for c in u'!"#%\'()*+,-./:;<=>?@[\]^_`{|}~’”“': print len(c.encode('utf-8')),

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3 3


>>> for c in u'!"#%\'()*+,-./:;<=>?@[\]^_`{|}~’”“'.encode('utf-8'): print c,ord(c),

! 33 " 34 # 35 % 37 ' 39 ( 40 ) 41 * 42 + 43 , 44 - 45 . 46 / 47 : 58 ; 59 < 60 = 61 > 62 ? 63 @ 64 [ 91 \ 92 ] 93 ^ 94 _ 95 ` 96 { 123 | 124 } 125 ~ 126 â 226 タ 128 ル 153 â 226 タ 128 ン 157 â 226 タ 128 ワ 156

出现问号的原因是您打断了 UTF-8 序列,并且序列的每个字节本身都不是有效字符。这些无效字符显示为问号。

如您所见,我的控制台(Python 2.7.5 的 IDLE)不打印问号,而是替换为不正确的字符。