Python curses печатает два символа при добавлении строки в кодировке utf-8

Я столкнулся с очень странной проблемой при попытке напечатать строки в кодировке UTF-8 в окне curses. Вот код, я расскажу о точной проблеме и вещах, которые я попробовал ниже.

# coding=UTF-8
import curses
import locale
import time
locale.setlocale(locale.LC_ALL, '')
code = locale.getpreferredencoding()



class AddCharCommand(object):
    def __init__(self, window, line_start, y, x, character):
        """
        Command class for adding the specified character, to the specified
        window, at the specified coordinates.
        """
        self.window = window
        self.line_start = line_start
        self.x = x
        self.y = y
        self.character = character


    def write(self):
        if self.character > 127:
            # curses somehow returns a keycode that is 64 lower than what it
            # should be, this takes care of the problem.
            self.character += 64
            self.string = unichr(self.character).encode(code)
            self.window.addstr(self.y, self.x, self.string)
        else:
             self.window.addch(self.y, self.x, self.character)


    def delete(self):
        """
        Erase characters usually print two characters to the curses window.
        As such both the character at these coordinates and the one next to it
        (that is the one self.x + 1) must be replaced with the a blank space.
        Move to cursor the original coordinates when done.
        """
        for i in xrange(2):
            self.window.addch(self.y, self.x + i, ord(' '))
        self.window.move(self.y, self.x)

def main(screen):
    maxy, maxx = screen.getmaxyx()
    q = 0
    commands = list()
    x = 0
    erase = ord(curses.erasechar())
    while q != 27:
        q = screen.getch()
        if q == erase:
            command = commands.pop(-1).delete()
            x -= 1
            continue
        command = AddCharCommand(screen, 0, maxy/2, x, q)
        commands.append(command)
        command.write()
        x += 1

curses.wrapper(main)

Вот ссылка на Gist.

Проблема в том, что когда я нажимаю è ключ (который имеет код ASCII 232), он не печатает только этот символ. Вместо этого строка ăè печатается по заданным координатам. Я пытался использовать self.window.addstr(self.x, self.y, self.string[1]) но это только привело к печатанию тарабарщины.

Затем я запустил приглашение Python, чтобы увидеть возвращаемое значение unichr(232).encode('utf-8') и это действительно строка длины 2.

Очень неожиданное поведение заключается в том, что, если я положу в screen.addstr(4, 4, unichr(232).encode(code)) в main он будет правильно отображать è характер, и только этот персонаж. Это также тот случай, если я сделаю write метод AddCharCommand класс для печати è характер, несмотря ни на что.

Проблема, конечно, не ограничивается è только это в значительной степени относится ко всем символам расширенного ASCII.

Я знаю, что расширенный ASCII с проклятиями немного ненадежен, но я просто не могу понять это поведение вообще. Для меня не имеет никакого смысла (для меня), что код работает должным образом, если я жестко кодирую код ASCII, но он добавляет другой символ, если я этого не делаю.

Я осмотрелся и прочитал довольно много материала о проклятиях, но я не смог найти решение этой проблемы. Я был бы очень признателен за любую помощь по этому вопросу, это сводит меня с ума.

Может быть, немного менее важно, но я был бы рад, если бы кто-то мог объяснить мне, почему screen.getch() возвращает неверный код ASCII для символов выше 127 и почему разница между реальным кодом ASCII и кодом, возвращаемым curses, составляет 64.

Заранее большое спасибо.

1 ответ

У меня работает нормально

c=screen.get_wch()
screen.addch(c)
Другие вопросы по тегам