为什么这个Python程序在Linux或WSL上退出时会挂起终端?

问题描述 投票:0回答:2

据我所知,该程序混淆了 Linux 和 WSL、python 2 和 3 上的终端仿真。

一旦程序退出,字符将不再回显,正常的终端功能也会停止。我相信这是因为当主线程退出时守护线程卡在 read(1) 中。

您可以通过键入“reset”(不回显)然后按 Enter 运行重置命令以重新初始化终端仿真来恢复终端。

您可以通过使用 t2.join() 在主线程退出之前强制 getchar 线程加入主线程来避免该问题。

但我更希望有一个干净、有效的解决方案——有什么想法吗?

谢谢!!!

import sys
import time
import platform
import threading

def getchar():
    import tty, termios, sys
    fd = sys.stdin.fileno()
    old_settings = termios.tcgetattr(fd)
    try:
        tty.setraw(sys.stdin.fileno())
        ch = sys.stdin.read(1)
    finally:
        termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
    print("you pressed '" + ch + "'\r")
    return ch

def getcharThread():
    while getchar() != 'q':
        time.sleep(0.1)
    print("thread exit\r")

t2 = threading.Thread(target = getcharThread)
t2.daemon = True
t2.start()

time.sleep(2)

运行该程序后,我希望终端仍能正常工作。相反,它不会回显字符(可能来自 setraw() 或 read())。

python multithreading tty getchar
2个回答
0
投票

您已经创建了一个将终端置于原始模式的线程,并且您已将其设置为“守护程序”线程 - 即程序在退出之前不会等待它完成。如果主线程在

getchar
线程之前退出,则
getchar
线程将突然终止。
finally
块将不会运行。您的程序退出时不会恢复终端状态,因此它仍处于原始模式。在原始模式下,您键入的字符不会出现在屏幕上,而是直接发送到正在运行的程序。运行“重置”命令会将终端恢复到“煮熟”模式。

如何解决这个问题取决于您想要做什么,但很可能您实际上并不希望将线程作为守护进程运行。我不知道你为什么要让它成为守护线程,所以我不能说得更具体。


0
投票

您是否在 Linux 或任何其他类 Unix 操作系统上运行该程序?如果是这样,那么您的程序的

tty.setraw(...)
调用会更改进程控制终端的模式,并且与您的程序可以执行的许多其他操作不同,它对控制终端所做的更改将不会自动被“清除”进程退出。部分原因是控制终端与启动程序的 shell 共享,并且我们希望能够从 shell 运行实用程序来更改终端设置。\

请参阅 https://www.linusakesson.net/programming/tty/index.php 了解有关 Linux/Unix 终端的更多信息。

© www.soinside.com 2019 - 2024. All rights reserved.