python - 如何在用户输入时中断 Python 程序?
问题描述
我正在编写一个以某种标准方式执行的程序,除非用户在终端中输入某些内容,在这种情况下,程序应该改变行为,例如
while True:
# do something here
def interrupt(user_input):
if user_input == "some command":
sys.exit(0) # e.g.
如何通过没有循环input()
来实现这一点?while
解决方案
这里最简单的解释是使用守护线程。
为了在 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()
与所描述的守护程序方法相比,这有两个优点:
- 您可以轻松地拥有多个
Event
s 并让您的程序以不同的方式运行,具体取决于这些事件。您还可以使用阻止Event.wait()
来代替Event.is_set()
. - 任何清理代码都可以直接由该
main()
函数管理。
推荐阅读
- javascript - 如何在 SPA 应用程序中处理“打算在新页面中打开链接”?
- java - 为什么代码在整数长度程序中跳过for循环
- php - 如何在订单电子邮件中添加产品的自定义属性(例如保质期)?(magento 2.3)
- c# - WebSocketClient ReceiveAsync 永远不会完成(单声道,Linux)
- java - 位置需要许可
- excel - 如何根据前一个单元格是否包含某些文本来更改单元格填充颜色?
- javascript - 如何使用纯 javascript 和 Jest 测试点击事件
- java - 通过 CrudRepository 使用 @Query 与 findAll() 哪个自定义查询更快?
- conan - XRlibrary 被另一个并发柯南进程锁定,等待...在 C++ 中
- java - 如何使用提供者注入集合