Python诅咒窗口上的getch不';t如果返回键';他在另一条线上

Python诅咒窗口上的getch不';t如果返回键';他在另一条线上,python,multithreading,ncurses,python-multithreading,python-curses,Python,Multithreading,Ncurses,Python Multithreading,Python Curses,当我自己运行这个函数时,一切都运行得非常好-发送了KEY_RESIZE,一切都很好。当我从线程内部调用getch()时,问题就出现了——键事件似乎工作得很好(我没有进行详尽或广泛的测试),但从来没有发送过键大小调整 我是否做错了什么,或者是否有任何方法可以修复此问题,以便在不考虑线程的情况下发送KEY_RESIZE 我尝试过在线程内外初始化屏幕,并在Python 3.4.3上的两个不同的终端模拟器(gnome终端和konsole)上进行初始化 打印发送到stderr(被重定向到另一个终端),因为

当我自己运行这个函数时,一切都运行得非常好-发送了KEY_RESIZE,一切都很好。当我从线程内部调用getch()时,问题就出现了——键事件似乎工作得很好(我没有进行详尽或广泛的测试),但从来没有发送过键大小调整

我是否做错了什么,或者是否有任何方法可以修复此问题,以便在不考虑线程的情况下发送KEY_RESIZE

我尝试过在线程内外初始化屏幕,并在Python 3.4.3上的两个不同的终端模拟器(gnome终端和konsole)上进行初始化


打印发送到stderr(被重定向到另一个终端),因为诅咒会破坏屏幕输出。在此代码中,我也没有处理修复终端的问题,因此您需要将其重置以使其恢复正常。

通常,诅咒不是线程安全的。如果在一个线程中完成所有工作,则可以使curses应用程序工作。否则,你会有意想不到的行为

ncurses有一个编译时配置,它提供了基本的支持(即更好的起点),但是您不太可能在预先打包的形式中遇到它,尽管它是在几年前引入的(请参见常见问题解答)

进一步阅读:

在初始化期间,ncurses为
SIGWINCH
和其他一些程序添加信号处理程序。使用
strace
,我可以看到python正在捕获
SIGWINCH
并忽略它:

import curses, threading, sys

def thread():
    a = curses.initscr()
    curses.noecho()
    curses.cbreak()
    a.keypad(True)
    while True:
        char = a.getch()
        if char == curses.KEY_RESIZE: 
            print("key_resize", file=sys.stderr)
        else:
            print("other", file=sys.stderr)

threading.Thread(target=thread).start()
2722)=?ERESTARTSYS(如果设置了SA_RESTART,则将重新启动)
2722---SIGWINCH{si_signo=SIGWINCH,si_code=si_KERNEL}---
2722 rt_sigreturn({mask=[]})=-1 EINTR(中断的系统调用)
2722 futex(0x7f94d4000c10,futex_WAIT_PRIVATE,0,NULL)=?ERESTARTSYS(如果设置了SA_RESTART,则将重新启动)
2722---SIGWINCH{si_signo=SIGWINCH,si_code=si_KERNEL}---
2722 rt_sigreturn({mask=[]})=-1 EINTR(中断的系统调用)
2722 futex(0x7f94d4000c10,futex_WAIT_PRIVATE,0,NULL)=?ERESTARTSYS(如果设置了SA_RESTART,则将重新启动)
2722---SIGINT{si_signo=SIGINT,si_code=si_KERNEL}---
2722 rt_sigreturn({mask=[]})=-1 EINTR(中断的系统调用)
2722写入(2,“在:\n中忽略异常”,82)=82
2722写入(2,“回溯(最近一次调用):\n”,35)=35
2722写入(2,“File\”/usr/lib/python3.4/threading.py\”,第1285行,在_shutdown\n“,66)=66
2722 open(“/usr/lib/python3.4/threading.py”,O|RDONLY | O|CLOEXEC)=4
由于python已经建立了一个信号处理程序,ncurses再也看不到
SIGWINCH
,也不会提供
KEY\u RESIZE
。这大概是在python中完成的,以缓解线程配置中的信号问题

或许相关信息:


这很公平-但即使在只有一个curses线程的情况下,如我上面的代码所示,它也不能像预期的那样工作。并且在其他线程上不使用标准输入/输出?(很难说…)我不知道你这是什么意思?在这个例子中,没有,在其他线程上没有使用stdin/out-这个例子代码是所有需要运行的东西,以显示我的意思。我会尝试测试它,但这个例子似乎只是一个更大程序的片段。最好的建议是,将代码裁剪成一个完整的(但很小的…)示例来说明问题。该示例是一个完整的小示例,说明了问题-当getch位于辅助线程上时,不会发送(或接收)键调整大小。我的问题格式设置得很糟糕,我已经对它进行了修改,以正确地反映它。
2722  <... futex resumed> )             = ? ERESTARTSYS (To be restarted if SA_RESTART is set)
2722  --- SIGWINCH {si_signo=SIGWINCH, si_code=SI_KERNEL} ---
2722  rt_sigreturn({mask=[]})           = -1 EINTR (Interrupted system call)
2722  futex(0x7f94d4000c10, FUTEX_WAIT_PRIVATE, 0, NULL) = ? ERESTARTSYS (To be restarted if SA_RESTART is set)
2722  --- SIGWINCH {si_signo=SIGWINCH, si_code=SI_KERNEL} ---
2722  rt_sigreturn({mask=[]})           = -1 EINTR (Interrupted system call)
2722  futex(0x7f94d4000c10, FUTEX_WAIT_PRIVATE, 0, NULL) = ? ERESTARTSYS (To be restarted if SA_RESTART is set)
2722  --- SIGINT {si_signo=SIGINT, si_code=SI_KERNEL} ---
2722  rt_sigreturn({mask=[]})           = -1 EINTR (Interrupted system call)
2722  write(2, "Exception ignored in: <module 'threading' from '/usr/lib/python3.4/threading.py'>\n", 82) = 82
2722  write(2, "Traceback (most recent call last):\n", 35) = 35
2722  write(2, "  File \"/usr/lib/python3.4/threading.py\", line 1285, in _shutdown\n", 66) = 66
2722  open("/usr/lib/python3.4/threading.py", O_RDONLY|O_CLOEXEC) = 4