Python中的N-curses:如何捕获和打印非ASCII字符?

时间:2019-05-30 07:06:29

标签: python unicode ncurses non-ascii-characters python-curses

我想用ncurses / python创建一个小程序,并能够使用法语和日语输入/输入。我知道我应该设置语言环境并使用unicode标准。

但是如何处理screen.getch()的结果呢?我想在ncurses窗口中显示键入的字符,无论使用哪种语言。

我了解到必须进行一些unicode转换,但找不到要做什么(我已经搜索了很多:对于业余爱好者而言,这种字符转换业务并不容易理解)。

其他问题:对于非ASCII字符,似乎必须使用addstr()而不是addch()。类似地,我应该使用getstr()而不是gethc()吗?

#!/usr/bin/python3
# -*- coding: utf-8 -*-
import curses
from curses import wrapper
import locale

locale.setlocale(locale.LC_ALL, '')

def main(scr):
    # Following lines are some sort of "proof of concept"
    # Indeed it print latin or japanese characters allright
    scr.addstr(0, 0, u'\u3042'.encode('utf-8')) # print あ
    scr.addstr(1, 0, 'é'.encode('utf-8'))       # print é

    # But here I would like to type in a character and have it displayed onscreen
    while (True):
        car = scr.getch()
        if car == 27: # = Escape key
            break
        else:
        # What should I put between those parenthesis to
        # print the typed character on the third line of the screen 
            scr.addstr(3, 0, ???? )

wrapper(main)

3 个答案:

答案 0 :(得分:0)

在Linux或其他类似Unix的系统中,终端应用程序(xterm等)通常启用utf8。这意味着非ASCII字符需要2、3或4个字节,并且尝试将其解码为UTF8和不完整的表示形式会引发UnicodeDecodeError。

这意味着您有两种可能:如果您只想在光标位置输出任何输入字符,只需输出输入字节而无需进一步处理:它们将由屏幕驱动程序进行汇编以组成初始字符

while (True):
    car = scr.getch()
    if car == 27: # = Escape key
        break
    else:
        scr.addstr(chr(car))

如果要在特定位置输出字符,或者出于任何原因想要在显示字符之前获取完整的unicode代码点,则可以尝试解码输入字节,直到不再收到UnicodeDecodeError为止:

>
b = b''                # empty byte string
while (True):
    car = scr.getkey()
    if ord(car) == 27: # = Escape key
        break
    else:
        b += car
        try:
            c = b.decode('utf8')
            scr.addstr(3,0,b)
            b = b''
        except UnicodeDecodeError:
            pass

答案 1 :(得分:-1)

unctrl是要使用的功能:

  

curses.unctrl( ch )

     

返回一个字符串,它是字符ch的可打印表示形式。控制字符显示为插入符号,后跟该字符,例如显示为 ^C 。保留打印字符。

答案 2 :(得分:-1)

getch / getkey在Python中已损坏。当按照文档所述设置编码时,它们应该返回一个字符,但是,每次调用该函数时,它们都会从UTF-8序列中逐个返回八位字节。您需要通过循环收集八位字节来解决缺陷,直到获得完整的序列。序列可以成功解码后就可以完成,否则就不完整。

与以下运行良好的程序进行比较(使用perl -C so-56373360.pl运行):

use Term::ReadKey qw(ReadKey ReadMode);
ReadMode 'raw';
while () {
    my $c = ReadKey 0;
    last if $c eq "\e"; # Escape
    print $c;
}
ReadMode 'restore';