nodelay()会导致Python curses程序退出。

7
我用python写了一个curses程序,它可以正常运行。但是,当我使用nodelay()时,在终端启动后程序立即退出,什么也没有显示(只会出现新的提示符)。
编辑:
以下代码可以重现该错误:
sc = curses.initscr()
sc.nodelay(1) # 删除此行允许程序正确运行
for angry in range(20): sc.addstr(angry, 1, "hi")
这是我的完整代码:
import curses, time, sys, random
def paint(x, y, i): #... def string(s, y): #...
def feed(): #...
sc = curses.initscr() curses.start_color() curses.curs_set(0) sc.nodelay(1) #########################################
# 初始化变量 + 颜色
for angry in range(20): try: dir = chr(sc.getch())
sc.clear()
feed()
#很多个if语句
body.append([x, y]) body.pop(0)
for point in body: paint(*point, i=2)
sc.move(height-1, 1) sc.refresh() time.sleep(wait)
except Exception as e: print sys.exc_info()[0], e sc.getch() curses.beep()
curses.endwin()
为什么会发生这种情况,如何安全地使用nodelay()?

1
尝试将你的代码缩减到最小,以重现错误。例如,您可以设置nodelay(),然后进入一个无限循环,当您使用getch()获取键时中断并退出。如果此错误在最小测试用例中消失,请找出已更改的内容。如果这仍然无法解决问题,请发布失败的测试用例。 - Philip
@Philip 好主意,已经这样做了,并发布了结果。 - ACarter
3个回答

8

我已经修改了你精简版的演示程序,使其基本功能能够正常工作。它具有非阻塞的getch()。如果在调用getch()时按住Q键,则程序结束,否则循环继续。

import curses, time

def main(sc):
    sc.nodelay(1)

    for angry in range(20):
        sc.addstr(angry, 1, "hi")
        sc.refresh()

        if sc.getch() == ord('q'):
            break

        time.sleep(1)

if __name__=='__main__':
    curses.wrapper(main)

我所做的最重要的更改是使用 curses.wrapper 来获取一个屏幕上下文,而不是使用 curses.initscr()。好处是,如果你的程序遇到未捕获的异常(例如按下^C),它会撤消所有对终端所做的更改,比如在退出前禁用光标。这对于调试非常有帮助。
从这里开始,我建议你逐步添加你的程序特性。Curses 在处理过程中有些棘手,如果一次性进行太多更改,就很难弄清楚是哪一个导致了问题。祝你好运!

1
问题已解决。添加主包装器后,我发现退出是因为getch()没有返回任何内容(因为没有输入可用),并且试图将其放入chr()中,而chr()无法处理空值。感谢您的帮助,在解决其他错误时,这将非常有用。 - ACarter

1
虽然我没有在Python中使用curses,但我目前正在使用C99,在Mac OS Catalina上使用clang编译。似乎除非您将程序步骤减慢至少1/10秒(例如usleep(100000)),否则nodelay()无法正常工作。我想缓冲区/缓冲区读取速度不够快,getch()或wgetch(win *)根本无法获取键盘输入,这会导致它失败(没有任何消息,甚至是“段错误”)。
因此,最好使用halfdelay(1),它等同于nodelay(win *,true)加上usleep(100000)。
我知道这是一个非常古老的主题(2012年),但问题仍然存在于2022年,所以我决定回复。

0

运行你的小测试程序时,使用sc.nodelay()行或不使用它并没有任何区别。

在两种情况下,屏幕上都没有打印任何东西...


关键是对我来说,使用sc.nodelay()后,curses窗口甚至没有打开,因此我无法做任何事情,因为没有可以操作的窗口。 - ACarter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接