Почему некоторые смайлики вызывают сбой Python/Idle в Ubuntu?

Я столкнулся с проблемой печати строк, содержащих смайлики, с использованием кода Python, работающего через Idle под Ubuntu 20.04LTS. Код отлично работает в Windows 10, но когда я пытаюсь запустить его в Ubuntu, попытка просмотреть некоторые строки приводит к сбою Python/Idle без отображения каких-либо полезных сообщений об ошибках. Сами смайлики кажутся проблемой, но не со всеми смайликами. Например, 128516 (ухмыляющееся лицо с улыбающимися глазами) — это нормально, а 128077 (большой палец вверх) вызывает сбой. Оба ПК работают под управлением Python 3.8.6, и в режиме ожидания отображается один и тот же номер версии.

Я создал фрагмент кода, чтобы продемонстрировать проблему.

def make_uchr(code: str):
    return chr(int(code.lstrip("U+").zfill(8), 16))

def calc1char(intdecimal):   
   # print()  128516 is ok...  128077 crashes on Ubuntu
          
    strhex = hex(intdecimal)[2:]
    strUhex  = "U+"+strhex
    stroutput = make_uchr(strUhex)
    return stroutput
    
def main():

    while True:
        try:
            print("Enter a decimal integer or ctrl+C to exit...")
            print("Try 128516, then try 128077.")
            strdecimal = input('Enter your choice: ')
            intdecimal = int(strdecimal)
            stroutput = calc1char(intdecimal)
            print("The corresponding character is:")
            print(stroutput)
            print()
        except KeyboardInterrupt:
            break

if __name__ == '__main__':
    main()

В Windows 10 этот код запускается без каких-либо проблем как при запуске через режим ожидания, так и при запуске из командной строки. В Ubuntu, когда он запускается с использованием Idle, происходит сбой Idle для некоторых кодов (например, 128077) без каких-либо видимых сообщений об ошибках. При запуске с терминала или с использованием Pycharm ожидаемый смайлик выводится на консоль. Недавно я обновился с Ubuntu 18.04LTS, и там тоже проявилась проблема.

В коде, где проблема стала очевидной, строки со смайликами будут корректно экспортироваться в текстовый файл, и у меня есть обходной путь для очистки просматриваемой строки при работе под Ubuntu, т.е.

if platform.system() == "Linux":  
    strmsg = (strmsg.encode("utf-8", errors='replace'))
    strmsg = str(strmsg.decode("ascii", errors='replace')) 

Это дает вопросительные знаки вместо других символов с кодами больше 127.

Однако мне любопытно, есть ли решение проблемы, а не обходной путь. Мы ценим любые предложения.


Вот еще один вариант с использованием примера графического интерфейса.

from tkinter import *
import tkinter as tk

def make_uchr(code: str):
    return chr(int(code.lstrip("U+").zfill(8), 16))

def calc1char(intdecimal):   
          
    strhex = hex(intdecimal)[2:]
    strUhex  = "U+"+strhex
    stroutput = make_uchr(strUhex)
    return stroutput

def printtoconsole():

    intdecimal = int(entry_decimal.get())
    stroutput = calc1char(intdecimal)
    print(stroutput)

def printtolabel():

    intdecimal = int(entry_decimal.get())
    stroutput = calc1char(intdecimal)    
    label_output.configure(text=stroutput)

def printtoentry():

    intdecimal = int(entry_decimal.get())
    stroutput = calc1char(intdecimal)
    entry_output.delete(0,len(entry_output.get()))
    entry_output.delete(0,len(entry_output.get()))
    entry_output.insert(INSERT, stroutput)
    
def printtotext():
    intdecimal = int(entry_decimal.get())
    stroutput = calc1char(intdecimal)
    text_box.delete("1.0", END)
    text_box.insert(INSERT,stroutput)    
    text_box.pack()
    
def main():

    window = tk.Tk()
    window.geometry("300x300")
    window.title("Emoticons  !")

    decimal_var = tk.StringVar()
    strentryoutput_var = tk.StringVar()
    strdecimal = "128516"

    decimal_var.set(strdecimal)

    global entry_decimal, text_box, label_output, entry_output

    button1=Button(window, text="Print()",   command=printtoconsole)
    button2=Button(window, text="To Label",   command=printtolabel)
    button3=Button(window, text="To Entry",   command=printtoentry)
    button4=Button(window, text="To Text",   command=printtotext)

    entry_decimal = Entry(window, textvariable = decimal_var)
    label_decimal = Label(window, text = "Enter decimal")
    label_output = Label(window, text = "label to show output")
    entry_output = Entry(window, textvariable = strentryoutput_var)
    text_output = Text(window)
    text_box = Text(text_output)

    button1.place(x=10, y=50)
    button2.place(x=10, y=100)
    button3.place(x=10, y=150)
    button4.place(x=10, y=200)

    label_decimal.place(x=10, y=10) 
    entry_decimal.place(x=100, y=10)
    label_output.place(x=100, y=100)
    entry_output.place(x=100, y=150, width=50)
    text_output.place(x=100, y=200, width=50, height=30)


if __name__ == '__main__':
    main()

Этот новый код использует графический интерфейс, чтобы предоставить 4 кнопки для печати смайлика на консоли, в виджете метки, в виджете ввода или текстовом виджете. Взяв десятичный диапазон от 128547 до 128549, в Windows 10 смайлики печатаются с каждой кнопки без проблем. В Ubuntu 20.04 все кнопки работают правильно для 128547 и 128549. Однако для 128548 кнопка печати не выводит, но не дает сбоя. Кнопки с надписью, вводом и текстом закрывают графический интерфейс, но оставляют консоль открытой и сбрасывают, показывая === Перезапуск: Shell === ›››. После этого возможен перезапуск из окна редактора с помощью F5. В Ubuntu кнопку входа нужно дважды щелкнуть, чтобы обновить смайлик, тогда как в Windows достаточно одного щелчка. Любопытно, но, возможно, дело в другом...


person IanSt1    schedule 30.10.2020    source источник
comment
С 3.10 в Windows в IDLE chr(128516)+' '+chr(128077) производит '???? ????' (без заливки). Это работает с года назад. В стандартном REPL, в командной строке, я вижу только квадратики (в отличие от вас видимо). На Mac Mohave в Терминале я вижу эмодзи. В IDLE, запущенном из терминала, эти конкретные кодовые точки замораживают Shell, но не посылают сообщения на терминал. Другие кодовые точки, отличные от BMP, отображаются с их представлениями `\U000#####'. Пока Shell заморожен, окно редактора все еще работает. Для какого аспекта проблемы вы спрашиваете об исправлении?   -  person Terry Jan Reedy    schedule 31.10.2020
comment
Возможно, стоит объяснить, чего я пытаюсь добиться в своем основном коде. Цель состоит в том, чтобы использовать Python для извлечения sms-сообщений из резервной копии xml системы обмена сообщениями моего телефона. Это включает в себя использование различных виджетов tkinter для получения графического вывода. Смайлики иногда могут быть включены в текст этих сообщений, а те, которые не приводят к сбою графического интерфейса, отображаются в виде одноцветных представлений, таких как дерево или текстовый виджет. Могут отображаться многие смайлики, например, с десятичными кодами в следующих диапазонах. 128512-128547; 128549-128555; 128557-128576   -  person IanSt1    schedule 31.10.2020
comment
В идеале цель состоит в том, чтобы найти решение проблемы, из-за которой не все смайлики будут выводиться на консоль Idle или отображаться в виджетах tkinter и действительно вызывать сбой программы без какого-либо предупреждения. В качестве отступления можно было бы найти исправление того факта, что определенные смайлики вызывают сбой, и каким-то образом уловить проблему до сбоя программы, позволяя смайликам, которые не вызывают проблемы, отображаться нормально. Опять же, я вижу проблему только при запуске этой программы Python через Idle на ПК с Ubuntu 20.04. При запуске под Windows 10 такой проблемы не наблюдал.   -  person IanSt1    schedule 31.10.2020
comment
Какой tcl/tk использует Ubuntu? Посмотрите Help =› О IDLE. Пожалуйста, определите «сбой»: Shell зависает? IDLE зависает? IDLE исчезает? tcl/tk поддерживает только первые 2**16 кодовых точек (плоскость BMP). Частичная поддержка в tkinter для *nix и Windows показа других (астральных) символов была добавлена ​​чуть больше года назад. (Они все еще путают редактирование.) Я открыл bugs.python.org/issue42225 для Mac и Ubuntu. проблемы. Это может помочь, если у вас есть учетная запись bpo и вы будете любопытны по этому вопросу, чтобы ответить на вопросы.   -  person Terry Jan Reedy    schedule 01.11.2020
comment
Версия версии Tk, отображаемая на ПК с Ubuntu, — 8.6.10. При запуске фрагмента кода, показанного в моем исходном вопросе, если ввести 128077, 128548 или 128556, Idle завершается сбоем, закрывая окно консоли и окно редактора. В то время у меня был открыт еще один редактор Idle, но этот оставался открытым. Наличие этого второго окна редактора не меняет способа отказа первого. Я посмотрю на страницы ошибок Python.   -  person IanSt1    schedule 02.11.2020
comment
Теперь я в замешательстве. Через несколько минут я повторил код графического интерфейса в Ubuntu, и поведение с десятичным числом 128548 было таким, как описано в редактировании вопроса выше. Однако при нажатии кнопки Print() консоль и окно редактора закрываются, а графический интерфейс остается открытым. Однако этот графический интерфейс не отвечает, кроме кнопок перетаскивания и изменения размера, и мне нужно использовать системный монитор Ubuntu, чтобы завершить процесс python3.8.   -  person IanSt1    schedule 02.11.2020


Ответы (2)


В дополнение к комментариям к Issue42225 Python Issues (https://bugs.python.org/issue42225), следующий код, запускаемый в окне терминала, дан как простой тест для систем Linux и MacOS, чтобы показать, вызовет ли символ проблему.

    $ wish
    % label .l -text 'paste an emoticon graphic here'

Если символ печатается, выводится следующее: .l

Для беспокойного персонажа типична следующая ошибка.

% X Error of failed request:  BadLength (poly request too large or internal Xlib length error)
  Major opcode of failed request:  139 (RENDER)
  Minor opcode of failed request:  20 (RenderAddGlyphs)
  Serial number of failed request:  599
  Current serial number in output stream:  599 

Также подразумевается, что пакет шрифтов fonts-noto-color-emoji вызывает сбой окон Tk в Ubuntu. Когда я удалил этот шрифт, сбой в Ubuntu прекратился, хотя некоторые символы смайликов больше не доступны.

Дальнейший поиск в Интернете по сообщению об ошибке RenderAddGlyphs обнаружил следующие ссылки по соответствующей теме. https://forum.manjaro.org/t/xorg-problem-while-running-tkinter-program-on-manjaro-python/37324/7 и https://bugs.launchpad.net/ubuntu/+source/git/+bug/1852985 Одно предложение из этой второй ссылки для установки пакета Unifonts. Хотя это не самое подробное представление символов смайликов, а также монохромное, оно имеет значительное преимущество, заключающееся в том, что Tk (версия: 8.6.10), работающий в Ubuntu 20.04, больше не падает, когда встречается один из ранее проблемных символов. До сих пор это оказалось достаточно хорошим обходным путем для моей первоначальной проблемы...

person IanSt1    schedule 10.12.2020

Вы можете исправить это, установив ttf-ancient-fonts-symbola в Ubuntu.

sudo apt-get install -y ttf-ancient-fonts-symbola
person Muhammad Yousuf Noor    schedule 02.02.2021