【发布时间】:2020-10-30 20:47:37
【问题描述】:
我在 Ubuntu 20.04LTS 下使用通过 Idle 运行的 Python 代码打印包含表情符号的字符串时遇到问题。该代码在 Windows 10 下运行良好,但是当我尝试在 Ubuntu 下运行它时,尝试查看一些字符串会导致 Python/Idle 崩溃而没有显示任何有用的错误消息。表情符号本身似乎是问题所在,但不是所有的表情符号。例如,128516(微笑的眼睛)是可以的,而 128077(竖起大拇指)会导致崩溃。两台电脑都运行 Python 3.8.6,Idle 显示相同的版本号。
我已经创建了一个代码 sn-p 来演示这个问题。
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 下,此代码在通过 Idle 运行和从命令提示符运行时都不会出现任何问题。在 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 的其他字符。
但是我很好奇是否有解决问题的方法而不是解决方法。任何建议将不胜感激。
这是另一个使用 GUI 示例的变体。
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()
此新代码使用 GUI 提供 4 个按钮,用于将表情符号打印到控制台、标签小部件、条目小部件或文本小部件。取十进制范围 128547 到 128549,在 Windows 10 上,从每个按钮打印表情符号没有问题。在 Ubuntu 20.04 上,对于 128547 和 128549,所有按钮都可以正常工作。但是对于 128548,打印按钮没有输出,但不会失败。标签、条目和文本按钮会导致 GUI 关闭,但让控制台保持打开并重置显示“=== Restart: Shell === >>>”。然后可以使用 F5 从编辑器窗口重新启动。 在 Ubuntu 上,输入按钮需要单击两次才能更新表情,而在 Windows 下,单击一次就足够了。很好奇,但也许是另一回事……
【问题讨论】:
-
Windows 上的 3.10 处于空闲状态,
chr(128516)+' '+chr(128077)产生'???? ????'(没有填充)。这从一年前就开始起作用了。在标准的 REPL 中,在命令提示符中,我只看到框(显然不像你)。在终端的 Mac Mohave 上,我看到了表情符号。在从终端启动的 IDLE 中,这些特定的代码点会冻结 Shell,但不会向终端发送消息。其他非 BMP 代码点与它们的 `\U000#####' 表示相呼应。当 Shell 被冻结时,编辑器窗口仍然有效。您要针对问题的哪个方面进行修复? -
也许值得解释一下我在主代码中想要实现的目标。目的是使用 Python 从我手机消息系统的 xml 备份中提取短信。这涉及使用各种 tkinter 小部件来提供图形输出。表情符号有时可以包含在这些消息的文本中,而那些不会导致图形界面崩溃的表情符号显示为单色表示,例如树或文本小部件。可以显示许多表情符号 - 例如具有以下范围的十进制代码的表情符号。 128512-128547; 128549-128555; 128557-128576
-
理想情况下,我们的目标是解决并非所有表情符号都会打印到空闲控制台或显示在 tkinter 小部件中并确实导致程序在没有任何警告的情况下崩溃的问题。回退将是找到解决某些表情符号导致崩溃的事实,并以某种方式能够在程序崩溃之前捕获问题,同时让不会导致问题的表情符号正常显示。同样,我只是在运行 Ubuntu 20.04 的 PC 上通过 Idle 运行此 Python 程序时才看到问题。在 Windows 10 下运行时,我没有遇到过这种问题。
-
Ubuntu 使用的是什么 tcl/tk?查看帮助 => 关于 IDLE。请定义“崩溃”:Shell 挂起? IDLE 冻结? IDLE消失了? tcl/tk 仅支持前 2**16 个代码点(BMP 平面)。 tkinter 对 *nix 和 Windows 显示其他(星体)字符的部分支持是在一年前添加的。 (他们仍然搞砸了编辑。)我为 mac 和 Ubuntu 问题打开了bugs.python.org/issue42225。如果您有 bpo 帐户并且对这个问题很关心回答问题,这可能会有所帮助。
-
Ubuntu PC 上显示的 Tk 版本为 8.6.10。运行我原始问题中显示的代码 sn-p 时,如果输入 128077、128548 或 128556,Idle 会通过关闭控制台窗口和编辑器窗口而失败。当时我确实打开了另一个空闲编辑器,但它仍然打开。第二个编辑器窗口的存在不会改变第一个编辑器窗口的失败方式。我会看看 Python 错误页面。
标签: python-3.x ubuntu-18.04 python-idle emoticons