【问题标题】:Cannot make warning sign visible on OSX Terminal and ncurses无法在 OSX 终端和 ncurses 上显示警告标志
【发布时间】:2014-11-13 22:38:19
【问题描述】:

这个在 OSX 10.6.8、python 3.4、Terminal.app 和字体 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 确实有警告标志的字形,但最让我困惑的是,如果我去编辑 -> 特殊字符,选择警告标志,然后单击插入,我在命令提示符处获得警告标志。同样使用 print() 会显示警告标志。

发生了什么事?

编辑:显然这是 OSX libc 库中的错误。看这里

How to get ncurses to output astral plane unicode characters

我尝试编译小程序获取wcinfo

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

因此,对于警告标志,我们得到一个 -1,表示不可打印字符。所以,这绝对是一个 OSX 问题,也是一个基本问题。

【问题讨论】:

  • 什么是stdscr?它不在文档的索引中。
  • @Terry:它是 ncurses 主屏幕句柄。它由包装器自动传递。

标签: python macos unicode ncurses


【解决方案1】:

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

$ 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-utf8utf8-unicodeodx 都是自制程序(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 个空格。然后您可以看到一些包含字节 E2 98 BA 和 E2 98 A2 的数据,但在这之间有三个空白,而不是您期望的 E2 98 A0。因此,警告符号的翻译被 Python 3 处理不当。

【讨论】:

  • 有趣...非常有趣。我会把它发布到 python-dev 上,听听他们的想法。
  • @eryksun:使用 Python 3.4.0(而不是 3.4.2,我尚未在我的 Mac 上创建的最新版本的 Python)和拼写修复 getpreferredencoding(),添加您建议的语言环境代码对显示没有影响。
  • 您在 Python 2 中遇到了同样的错误?如果是这样,它可能是一个与 Python 无关的 curses 库错误。它适用于带有 ncurses 5.9.20140118 的 Linux。
  • 关于 Python 错误的问题应该转到 python-list(无需订阅即可通过 news.gmane.net 访问),而不是 python-dev。
  • @eryksun:我在 Python 2.7.6 中使用了 stdscr.addstr(i, 0, u'\u263a \u26a0 \u2622'.encode("utf-8")),但没有得到中间三角形警告标志 U+26A0。我弄乱了一些 C 代码,看看我能得到什么。终端能够显示字符,所以问题出在显示数据的软件的某些方面。
【解决方案2】:

在 3.4.2 Win 7 上使用 Lucida 控制台在 Idle 的 tkinter 文本小部件中可以正常打印警告标志。此外,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 无法正确编码”的评论必须被理解为“用于为 Mac OS X 构建的特定 Python 版本”(尽管我不知道它是否在 python-dev 上发布时非常合格)。我在 OS X 10.10 Yosemite 上使用系统提供的 Python 2.7.6 或 3.4.0 构建。我确信这不是一般的 Python 错误——但它似乎可以在两台不同的 Mac(Stefano 和我的)上重现。 stdscr 是来自 curses 模块(或 curses wrapper 模块)的名称,至少在 Mac 上是这样。
  • 'u2620'.encode('utf-8' == b''\xe2\x9a\xa0' 在 Mac 上是否失败?如果不是,我强烈怀疑不是,那么 Python is 正确编码了字符。据我所知,Stefano 和你只有在使用 stdscr/curses 时遇到问题,它包装了系统诅咒。因此,stdscr.addstr 似乎得到了正确编码的字节——通过分离编码和调用很容易测试。我和其他回复 Stefano 帖子的开发人员都怀疑系统中的问题是诅咒,而不是 Python 包装器。包装器不太可能选择性地过滤掉警告标志。
  • 我试过这段代码(运行时分布在四行):if 'u2620'.encode('utf-8') == b'\xe2\x9a\xa0': print("Equal") else: print("Unequal") with Python 3;它打印不相等。 (我在文件中也有 import localelocale.setlocale(locale.LC_ALL, '')encoding = locale.getpreferredencoding() 行。我在 Python 2 中使用了 print "String" 表示法;它也打印了 Unequal。
  • @JonathanLeffler,使用u'\u26a0'.encode('utf-8') == b'\xe2\x9a\xa0'。这应该适用于 2.6、2.7 和 3.3+。
  • @eryksun:您建议的符号在 2.7.6 和 3.4.0 中都能正常工作,在两种情况下都打印“Equal”(当然,使用适当的 print 符号)。此外,FWIW,在 Python 3 中运行 print(u'\u263a \u26a0 \u2622'.encode("utf-8")) 和 Python 2 中的相应代码(周围没有诅咒)会打印“☺ ⚠ ☢”,所以问题可能出在 curses 库的 Python 接口或 curses 库本身中,而不是比在原始 Python 中。
猜你喜欢
  • 2016-06-11
  • 2020-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-17
  • 2023-01-12
  • 2021-03-18
  • 1970-01-01
相关资源
最近更新 更多