在Windows上使用curses
模块(via this PDCurses),我试图打破KeyboardInterrupt
异常,但是当我按ctrl + c时它不会升起。
一些提炼代码:
from curses import wrapper
items = ['a', 'very', 'long', 'list', 'of', 'strings']
def main(screen):
for item in items:
screen.addstr(0, 0, item)
screen.getch()
screen.refresh()
wrapper(main)
items
列表很长,现在我无法停止执行。我必须反复按键直到我结束。天堂禁止我曾在while True:
中试过这个!
按ctrl + c时,不会引发异常。它确实传递给我的getch()
3
。在getch
收到3
时是否手动提高SOP,或者是否有更合适的方法可以避免吞咽KeyboardInterrupt
?
答案 0 :(得分:2)
默认curses
使用raw
模式,从文档中关闭中断/退出/暂停等
在原始模式下,正常行缓冲和处理中断,退出, 暂停,流量控制键关闭;人物是 呈现给逐个诅咒输入函数
来自C的诅咒documentation:
这两个函数(
raw
和cbreak
)之间的区别在于 控制字符的方式如挂起(CTRL-Z),中断和退出 (CTRL-C)传递给程序。 在raw()
模式下这些 字符直接传递给程序而不生成 信号。强>
由于python在发送KeyboardInterrupt
时会引发SIGINT
,因此预计不会引发它3
。您看到的getch
表示中断。
由于这是C库处理的事情,因此无法避免异常的“吞咽”。但是,您可以使用3
的简单包装器检查何时返回{{1}}并相应地引发错误。
答案 1 :(得分:0)
使用UGETCHAR_(如下实现)代替getch
def UGETCHAR_(scr):
import curses
h = scr.getch()
if h == 3:
raise KeyboardInterrupt
if h == 26:
raise EOFError
return h
让我解释一下。
因此,首先调用该函数时,它将导入curses
[import curses
]。
接下来,它将运行您正在使用的getch()并将结果放入名为h
的变量中。 [h = scr.getch()
]
然后,如果raise KeyboardInterrupt
为3(h
[^C
],则引发KeyboardInterrupt [if h == 3:
];如果{{1,则引发EOFError [raise KeyboardInterrupt
] }}是26(h
)[^Z
]。
最后,它返回if h == 26:
[h
]的值。
答案 2 :(得分:0)
很久以前就有人问过这个问题,但我遇到了完全相同的问题。我想要一个使用 curses 的 Python 程序在 Windows 和 Linux 上运行。 KeyboardInterrupt 在 Linux 上完全按预期工作,但在 Windows 上则不然。我尝试了所有的 curses 设置功能,但始终无法使用 Ctrl+C 来中断执行。
下面的代码似乎有效,但并不理想。到目前为止我找不到更好的方法。这种方法在 Windows 上的问题在于它不会中断。在检查输入之前,代码将完成它在当前循环迭代中所做的任何工作。 (它在 Linux 上仍然可以完美运行。)
import curses
import time
def Main(stdscr):
stdscr.addstr(0, 0, "Main starting. Ctrl+C to exit.")
stdscr.refresh()
try:
i = 0
while True:
i = i + 1
stdscr.addstr(1, 0, "Do work in loop. i=" + str(i))
stdscr.refresh()
time.sleep(1)
stdscr.nodelay(1) # Don't block waiting for input.
c = stdscr.getch() # Get char from input. If none is available, will return -1.
if c == 3:
stdscr.addstr(2, 0, "getch() got Ctrl+C")
stdscr.refresh()
raise KeyboardInterrupt
else:
curses.flushinp() # Clear out buffer. We only care about Ctrl+C.
except KeyboardInterrupt:
stdscr.addstr(3, 0, "Ctrl+C detected, Program Stopping")
stdscr.refresh()
finally:
stdscr.addstr(4, 0, "Program cleanup")
stdscr.refresh()
time.sleep(3) # This delay just so we can see final screen output
curses.wrapper(Main)
Linux 上的输出:
Main starting. Ctrl+C to exit.
Do work in loop. i=4
Ctrl+C detected, Program Stopping
Program cleanup
Windows 上的输出:
Main starting. Ctrl+C to exit.
Do work in loop. i=6
getch() got Ctrl+C
Ctrl+C detected, Program Stopping
Program cleanup