Python 无法使警告标志在OSX终端和ncurses上可见

Python 无法使警告标志在OSX终端和ncurses上可见,python,macos,unicode,ncurses,Python,Macos,Unicode,Ncurses,OSX 10.6.8、python 3.4、Terminal.app和font Menlo上的这个简单程序打印三个unicode字符:一个笑脸、一个警告标志和一个放射性符号,或者我应该说应该打印,因为事实上我只得到第一个和最后一个。警告标志不在那里 from curses import wrapper def main(stdscr): # Clear screen stdscr.clear() for i in range(1, 11): stdsc

OSX 10.6.8、python 3.4、Terminal.app和font Menlo上的这个简单程序打印三个unicode字符:一个笑脸、一个警告标志和一个放射性符号,或者我应该说应该打印,因为事实上我只得到第一个和最后一个。警告标志不在那里

from curses import wrapper

def main(stdscr):
    # Clear screen
    stdscr.clear()

    for i in range(1, 11):
        stdscr.addstr(i, 0, '\u263a \u26a0 \u2622'.encode("utf-8"))

    stdscr.refresh()
    stdscr.getkey()

wrapper(main)
此外,如果我打开Font Book,显然Menlo确实有一个警告符号的标志符号,但最让我困惑的是,如果我转到Edit->Special characters,选择警告符号,然后单击Insert,我会在命令提示下看到一个警告符号。还可以使用print()显示警告标志

发生什么事了

编辑:显然这是OSX libc库中的一个bug。看这里

我试着编译这个小程序来获取wcinfo

sbo@sbos-macbook:~$ ./wcinfo 26a0
Code 26A0: width -1 
sbo@sbos-macbook:~$ ./wcinfo 263a
Code 263A: width 1 punct graph print 

因此,对于警告标志,我们得到了-1,这意味着不可打印字符。因此,这肯定是OSX的一个问题,也是一个基本问题。

当我在Mac OS X 10.10(约塞米蒂)终端上使用Lucida Console作为字体运行它时,我得到如下输出:

$ printf "%s\n" u+263a u+0020 u+26a0 u+0020 u+2622 | unicode-utf8
☺ ⚠ ☢
$  printf "%s\n" u+263a u+0020 u+26a0 u+0020 u+2622 | unicode-utf8 | odx
0x0000: E2 98 BA 20 E2 9A A0 20 E2 98 A2 0A               ... ... ....
0x000C:
$ printf "%s\n" u+263a u+0020 u+26a0 u+0020 u+2622 | unicode-utf8 | utf8-unicode
(standard input):
0xE2 0x98 0xBA = U+263A
0x20 = U+0020
0xE2 0x9A 0xA0 = U+26A0
0x20 = U+0020
0xE2 0x98 0xA2 = U+2622
0x0A = U+000A
$
程序
unicode-utf8
utf8-unicode
odx
都是自制的brew程序(unicode程序并不特别优雅),但它们允许我使用unicode进行分析工作。而且,至少在我的电脑上,这三个符号都出现了。当它们没有用空格分隔时,三角形和辐射符号在屏幕上重叠(与浏览器不同),这就是我添加空格的原因:

☺⚠☢
因此,我建议仔细查看您显示的脚本的输出。您可能会看到编码问题,或者curses库可能没有正确意识到UTF-8,或者

当我使用Python 2运行时,我得到:

\u263a \u26a0 \u2622
\u263a \u26a0 \u2622
\u263a \u26a0 \u2622
\u263a \u26a0 \u2622
\u263a \u26a0 \u2622
\u263a \u26a0 \u2622
\u263a \u26a0 \u2622
\u263a \u26a0 \u2622
\u263a \u26a0 \u2622
\u263a \u26a0 \u2622
当我使用Python 3运行时,我得到:

☺   ☢
☺   ☢
☺   ☢
☺   ☢
☺   ☢
☺   ☢
☺   ☢
☺   ☢
☺   ☢
☺   ☢
这意味着我可以重现这个问题,但这似乎是Python中的问题,而不是终端中的问题

我跑:

$ python3 so.26919799.py > py3.output
$ odx py3.output
输出的相关部分是:

0x1D60: 20 20 20 20 20 20 20 1B 5B 36 35 3B 31 48 20 20          .[65;1H  
0x1D70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                   
* (5)
0x1DD0: 20 20 20 20 20 20 20 20 20 20 20 08 20 08 1B 5B              . ..[
0x1DE0: 34 68 20 1B 5B 34 6C 1B 5B 48 0A E2 98 BA 20 20   4h .[4l.[H....  
0x1DF0: 20 E2 98 A2 0D 0A E2 98 BA 20 20 20 E2 98 A2 0D    ........   ....
0x1E00: 0A E2 98 BA 20 20 20 E2 98 A2 0D 0A E2 98 BA 20   ....   ........ 
0x1E10: 20 20 E2 98 A2 0D 0A E2 98 BA 20 20 20 E2 98 A2     ........   ...
0x1E20: 0D 0A E2 98 BA 20 20 20 E2 98 A2 0D 0A E2 98 BA   .....   ........
0x1E30: 20 20 20 E2 98 A2 0D 0A E2 98 BA 20 20 20 E2 98      ........   ..
0x1E40: A2 0D 0A E2 98 BA 20 20 20 E2 98 A2 0D 0A E2 98   ......   .......
0x1E50: BA 20 20 20 E2 98 A2 1B 5B 3F 31 6C 1B 3E 1B 5B   .   ....[?1l.>.[
0x1E60: 6D 0D 1B 5B 35 34 42 1B 5B 4B 1B 5B 36 35 3B 31   m..[54B.[K.[65;1
0x1E70: 48 1B 5B 32 4A 1B 5B 3F 34 37 6C 1B 38 0D 1B 5B   H.[2J.[?47l.8..[
0x1E80: 3F 31 6C 1B 3E                                    ?1l.>
0x1E85:

0x1D60:
表示文件中的字节偏移量。我的终端窗口是110宽65深,所以有很多空白是由输出生成的。
*(5)
行表示还有5行16个空格。然后您可以看到一些包含字节e298ba和e298a2的数据,但在它们之间有三个空格,而不是您所期望的e298a0。因此,Python3错误地处理了警报符号的翻译。

在Idle的tkinter文本小部件中,在3.4.2 Win 7的Lucida控制台上,警告标志可以很好地打印出来。此外,Python正确地对字符进行utf-8编码和解码。这与Stefano发布到py-dev的“python无法将\u26a0(警告符号)正确编码为utf-8”相反

>>> s='\u26a0'
>>> s
'⚠'  # up-pointing triangle /_\ with ! inside
>>> b=s.encode('utf-8')
>>> b
b'\xe2\x9a\xa0'  # E2 9A A0 is what Jonathan said is correct.
>>> b.decode('utf-8')
'⚠'

stdscr
是OSX上额外的内置名称吗?还是缺少定义它的代码?

有趣。。。非常有趣。我将把它发布到python开发人员那里,听听他们对它的看法。@eryksun:使用python 3.4.0(而不是3.4.2,最新版本的python,我还没有在Mac上创建),拼写修复
getpreferredencoding()
,添加您建议的区域设置代码不会对显示产生影响。您在python 2中遇到同样的错误吗?如果是这样,那可能是一个与Python无关的curses库bug。在Linux w/ncurses 5.9.20140118中它对我有效。关于Python bug的问题应该转到Python列表(通过news.gmane.net进行访问,无需订阅),而不是Python-dev。@eryksun:我使用了
stdscr.addstr(I,0,u'\u263a\u26a0\u2622'.encode(“utf-8”)
和Python 2.7.6,但没有得到中间的三角形警告符号u+26A0。我正在处理一些C代码,看看能得到什么。终端能够显示字符,因此问题在于显示数据的软件的某些方面。什么是
stdscr
?它不在文档的索引中。@Terry:它是ncurses主屏幕句柄。它是由包装器自动传递的。任何关于“Python未能正确编码”的评论都必须理解为“对于为在Mac OS X上使用而构建的特定版本的Python”(尽管我不知道它在Python dev上发布时是否如此限定)。我使用的是系统提供的Python2.7.6或3.4.0构建在OS X 10.10 Yosemite上。我确信这不是一个普通的Python bug——但它似乎可以在两个单独的Mac(Stefano's和我的Mac)上复制。
stdscr
是来自
curses
模块(或
curses
wrapper
模块)的名称,至少在Mac上是这样。是否
'u2620'('utf-8'==b'\xe2\x9a\xa0'
在Mac上失败?如果没有,而且我强烈怀疑没有,那么Python对字符进行了正确编码。据我所知,Stefano和您只在使用stdscr/curses时遇到了问题,stdscr/curses包装了系统curses。因此,stdscr.addstr似乎得到了正确编码的字节——通过分离编码d调用。我和响应Stefano帖子的其他开发人员都怀疑系统中的问题是诅咒,而不是Python包装。包装不太可能选择性地过滤掉警告标志。我尝试了以下代码(运行时分四行):
if'u2620.encode('utf-8')==b'\xe2\x9a\xa0':print(“Equal”)否则:用Python 3打印(“不相等”)
;它打印不相等。(我在文件中有
import locale
locale.setlocale(locale.LC_ALL)、
encoding=locale.getpreferredencoding()
。我使用了
print“String”
Python 2的表示法;它的打印格式也不相同。@JonathanLeffler,使用
u'\u26a0'.encode('utf-8')==b'\xe2\x9a\xa0'
。这在2.6、2.7和3.3+中应该可以使用。@eryksun:您建议的表示法在2.7.6和3.4.0中都可以正确使用,在这两种情况下打印“相等”(当然,使用适当的
打印
表示法)另外,FWIW,在Python 3中运行
print(u'\u263a\u26a0\u2622'.encode(“utf-8”)
,以及相应的