如何在Python交互式控制台中捕获“Ctrl-D”?

13

我有一个服务器在后台运行的线程中,我使用python -i启动它,以便能够获得交互式控制台,可以在其中输入命令并轻松调试。但是当我按下Ctrl-D时,由于服务器仍在后台线程中运行,控制台将无法退出。如何捕获Ctrl-D事件以便我可以优雅地关闭服务器并退出?我知道如何使用信号捕获Ctrl-C,但由于我经常按Ctrl-D,通常会得到一个“挂起”的终端,这真的很烦人。

谢谢!

服务器代码(简化)如下:

import threading
import atexit

class WorkerThread(threading.Thread):
    def __init__(self):
        super(WorkerThread, self).__init__()
        self.quit = False

    def run(self):
        while not self.quit:
            pass

    def stop(self):
        self.quit = True

def q():
    print "Goodbye!"
    t.stop()

atexit.register(q)

t = WorkerThread()
t.start()

我使用python -i test.py来运行它,以获得一个Python控制台。

2个回答

18

使用raw_input(在Python 3.x中使用input)。按下Ctrl+D将导致EOFError异常。

try:
    raw_input()
except EOFError:
    pass

更新

使用atexit-退出处理程序

import atexit

def quit_gracefully():
    print 'Bye'

atexit.register(quit_gracefully)

服务器不会读取任何输入,而是在python控制台中使用python -i运行。该控制台用于输入python表达式以调试服务器。 - Chi Zhang
2
@ChiZhang,在t.start()之前调用t.setDaemon(True) - falsetru
我能否使用 Getch (https://dev59.com/hHRB5IYBdhLWcg3wyqKo#510364) 来捕获它?@falsetru - alper
@alper,请发布一个单独的问题,而不是评论,这样其他人就可以回答你了。 - falsetru
1
我通过将捕获的字符与“\x04”进行比较来处理它。 - alper
raw_input(以及Python3中的input)都是阻塞式的。这意味着如果您有一个在循环中运行的程序,它将无法正常工作。 - Charles D Pantoga

3

在我看来,这里的答案是正确的。如果存在非守护线程并且按下^D,那么atexit不会保护你。 - MoxieBall

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