首页 > 解决方案 > 如何在用户输入时中断 Python 程序?

问题描述

我正在编写一个以某种标准方式执行的程序,除非用户在终端中输入某些内容,在这种情况下,程序应该改变行为,例如

while True:
    # do something here

def interrupt(user_input):
    if user_input == "some command":
        sys.exit(0) # e.g.

如何通过没有循环input()来实现这一点?while

标签: pythonpython-3.x

解决方案


这里最简单的解释是使用守护线程。

为了在 Python 中实现这一点,您可以使用多线程。为此,有threading模块。

daemon=True通过在创建线程时进行设置,您的守护程序将在后台运行。

下面是一个简单的例子。您的主要逻辑将进入该main功能。while True无限循环侦听用户输入并在用户输入匹配某个预定义值(在本例中)时终止程序"kill"

import sys
import threading

def main():
    print('Main program')
    while True:
        pass
        # Rest of main program

main_thread = threading.Thread(name='main program',
                               target=main, daemon=True)
main_thread.start()
while True:
    if input().lower() == 'kill':
        print('Terminating program')
        # Add some possible cleanup code here
        sys.exit(0)

请注意 Python 文档中有关如何停止守护线程的重要信息:

守护程序线程在关闭时突然停止。它们的资源(如打开的文件、数据库事务等)可能无法正常释放。如果您希望线程优雅地停止,请将它们设为非守护进程并使用合适的信号机制,例如事件。

也就是说,这种方法可能足以满足您的目的。根据您的程序逻辑,如果需要一些清理代码,可以在退出之前完成——因为一旦sys.exit(0)调用,守护线程将被突然终止。

然而,更通用的解决方案是使用threading.Event.

这是与上述方法截然不同的方法,因为我们创建了一个常规的非守护线程并将 an 传递Event给它。这一次,我们没有在用户输入时突然退出程序,而是set使用Event.

并行,而不是while True无限循环,该main函数在设置后使用非阻塞is_set()来中断循环Event

import threading

def main(e):
    print('Main program')
    while not e.is_set():
        pass
        # Rest of main program
    print('Exiting')
    # Add some possible cleanup code here

e = threading.Event()

main_thread = threading.Thread(name='main program',
                               target=main, args=(e,))
main_thread.start()

while True:
    if input().lower() == 'kill':
        print('Terminating program')
        e.set()
        break

main_thread.join()

与所描述的守护程序方法相比,这有两个优点:

  1. 您可以轻松地拥有多个Events 并让您的程序以不同的方式运行,具体取决于这些事件。您还可以使用阻止Event.wait()来代替Event.is_set().
  2. 任何清理代码都可以直接由该main()函数管理。

推荐阅读