gpt4 book ai didi

python - 当 xterm 调整大小时,getch() 未返回 KEY_RESIZE

转载 作者:行者123 更新时间:2023-12-01 08:22:45 28 4
gpt4 key购买 nike

我在 Debian Linux 9 机器上使用 Python 3.7,并带有标准 readline 和curses 模块。当在 xterm 中运行并且调整 xterm 大小时,以下代码应输出“True”:

import readline
import os
import curses

terminal_resized = False

def main(stdscr):
global terminal_resized
ch = stdscr.getch()
if ch == curses.KEY_RESIZE:
terminal_resized = True

os.unsetenv('LINES')
os.unsetenv('COLUMNS')

curses.wrapper(main)
print(terminal_resized)

但是,输出为“False”,表明对 getch() 的调用未返回 KEY_RESIZE。事实上,它返回 -1。

请注意,如果我不导入 readline 模块,代码将按预期工作。

在谷歌搜索此问题的解决方案时,我遇到了 2016 年的一篇帖子,指出导入 readline 和curses 模块时存在冲突。基本上,readline 模块设置“LINES”和“COLUMNS”环境变量,这会干扰 ncurses 的内置 SIGWINCH 信号处理程序,这最终负责在调整终端大小时 getch() 返回 KEY_RESIZE。这就是为什么我在那里调用 unsetenv() 的原因。

但是,这些 un​​setenv() 调用显然在 2019 年没有任何效果。事实上,当我在导入 readline 后尝试打印出所有环境变量时,我在输出中没有看到“LINES”或“COLUMNS”的引用。不过,我还是把这些对 unsetenv() 的调用放在那里,看看它是否会做任何有用的事情。

有谁知道如何让curses getch()方法返回KEY_RESIZE,就像在Python 3.7中导入readline模块时应该的那样?

最佳答案

在使用strace进行快速检查时,我可以看到在ncurses为SIGWINCH设置其处理程序后,某些东西将SIGWINCH处理程序重置回SIG_DFL(无操作) 。 readline 的符号表有这些相关的入口点:

_rl_block_sigwinch
_rl_redisplay_after_sigwinch
_rl_release_sigwinch
_rl_sigwinch_resize_terminal
rl_catch_sigwinch

阅读行注释的文档

    o A new variable, rl_catch_sigwinch, is available to application
writers to indicate to readline whether or not it should install its
own signal handler for SIGWINCH, which will chain to the calling
applications's SIGWINCH handler, if one is installed;

但是,阅读 libpython3.5 的源代码,看来开发者没有考虑到这一点:

/* Helper to initialize GNU readline properly. */

static void
setup_readline(readlinestate *mod_state)
{
...
rl_readline_name = "python";
/* Force rebind of TAB to insert-tab */
rl_bind_key('\t', rl_insert);
/* Bind both ESC-TAB and ESC-ESC to the completion function */
rl_bind_key_in_map ('\t', rl_complete, emacs_meta_keymap);
rl_bind_key_in_map ('\033', rl_complete, emacs_meta_keymap);
#ifdef HAVE_RL_RESIZE_TERMINAL
/* Set up signal handler for window resize */
sigwinch_ohandler = PyOS_setsig(SIGWINCH, readline_sigwinch_handler);
#endif

This change in 2016似乎与您所看到的问题有关(即兴看来,似乎在没有解决旧问题的情况下引入了新问题)。如果为 readline 添加的信号处理程序没有链接到 ncurses 中的信号处理程序,则不再使用后者,并且 ncurses 无法返回 KEY_RESIZE。另外,如果 readline 首先设置其处理程序,ncurses 将不会设置其处理程序。

后者似乎是这种情况:import readline 调用模块初始化来设置信号处理程序。当 Pythoncurses 包装器调用 initscr 时,ncurses 信号处理程序将被初始化。 PyInit__curses(在导入curses上调用的函数)中没有这样做,因为这会清除屏幕。或者,如果 newterm 被调用(这不会清除屏幕),ncurses 会初始化其信号处理程序,但 Python 不会这样做。

可以通过加载 ncurses(或 ncursesw!)库并调用 newterm 来解决此问题通过 endwin,在 import 语句之前执行此操作。这看起来工作量很大。我建议打开错误报告。

供引用:

关于python - 当 xterm 调整大小时,getch() 未返回 KEY_RESIZE,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54520435/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com