python - Python,使用多线程退出带有用户输入的 While 循环(cntrl+c 不起作用)
问题描述
我有一个系统利用函数monitor(),我想通过键入数字零exit_collecting() 来运行它,直到用户停止它。我不想突然结束程序,因为这会否定后续代码。
我尝试使用多线程运行这两个函数,exit_collecting() 和monitor(),让monitor() 一直运行,直到用户通过键入零停止它,exit_collecting()。
我下面的代码抛出了一堆回溯。我是这方面的新手,任何想法,任何帮助都会很棒。谢谢你。顺便说一句,我最初尝试使用“try with an except for KeyboardInterrupt”,但是当使用 IDLE(Spyder)时,ctrl-c 组合不起作用(分配给“copy”),当我使用 ctrl-c 时不起作用也可以从 Linux 的控制台运行它。
def exit_collecting():
try:
val = int(input("Type 0 to exit data collection mode"))
if val == 0:
flag = 0
except:
print(val,"typo, enter 0 to exit data collection mode")
def monitor():
import time
import psutil
flag = 1
while flag > 0:
time.sleep(1)
print("cpu usuage:",psutil.cpu_percent())
from multiprocessing import Process
p1 = Process(target=exit_collecting)
p1.start()
p2 = Process(target=monitor)
p2.start()
p1.join()
p2.join()
解决方案
您的多处理版本注定要失败,因为每个进程都有自己的内存空间并且不共享相同的变量flag
。它可以通过多处理来完成,但您必须使用flag
使用共享内存的实现。
使用线程的解决方案要简单得多,只要您进行一次更改,您的代码就应该可以工作。您忽略了声明flag
为全局的。这是确保函数exit_collecting
和monitor
正在修改相同变量所必需的。如果没有这些声明,每个函数都在修改一个局部 flag
变量:
def exit_collecting():
global flag
try:
val = int(input("Type 0 to exit data collection mode"))
if val == 0:
flag = 0
except:
print(val,"typo, enter 0 to exit data collection mode")
def monitor():
global flag
import time
import psutil
flag = 1
while flag > 0:
time.sleep(1)
print("cpu usuage:",psutil.cpu_percent())
from threading import Thread
p1 = Thread(target=exit_collecting)
p1.start()
p2 = Thread(target=monitor)
p2.start()
p1.join()
p2.join()
但是也许可以通过使monitor
线程成为守护线程来简化上面的代码,即当所有非守护线程终止时它将自动终止的线程(如当前所写,似乎函数monitor
可以在处理中的任何点终止) . 但无论如何,主线程可以执行exit_collecting
正在执行的功能。现在没有理由不能使用键盘中断(只要您input
在主线程中等待一条语句):
def monitor():
import time
import psutil
while True:
time.sleep(1)
print("cpu usuage:",psutil.cpu_percent())
from threading import Thread
p = Thread(target=monitor)
p.daemon = True
p.start()
try:
input("Input enter to halt (or ctrl-C) ...")
except KeyboardInterrupt:
pass
"""
When the main thread finishes all non-daemon threads have completed
and therefore the monitor thread will terminate.
"""
更新:允许monitor
线程正常终止并允许键盘中断
我已经简化了逻辑 a 但只是使用一个简单的全局标志 ,terminate_flag
最初False
,它只能由monitor
线程读取,因此不必将其显式声明为全局:
terminate_flag = False
def monitor():
import time
import psutil
while not terminate_flag:
time.sleep(1)
print("cpu usuage:", psutil.cpu_percent())
from threading import Thread
p = Thread(target=monitor)
p.start()
try:
input('Hit enter or ctrl-c to terminate ...')
except KeyboardInterrupt:
pass
terminate_flag = True # tell monitor it is time to terminate
p.join() # wait for monitor to gracefully terminate
推荐阅读
- java - 在查询的任何表中都找不到列(名称)(或 SLV 未定义)
- c++ - CLion 没有调试我的目标之一 - 立即“进程以退出代码 0 完成”
- javascript - 基于数组的 jQuery 选择选项在 Safari 中不起作用
- vba - VBA - 具有命名范围内的值的组合框
- python - 在字符上拆分字符串,除非转义
- python - Python 的 __slots__ 和数据类的(内存方面和访问时间方面)比较是什么
- amazon-web-services - VPC 设置将 Elastic Beanstalk URL 的访问限制为仅 API 网关?
- c# - 画很多线很慢
- java - 根据在不同列中测试的条件创建具有组标签的新列
- php - 您可以扫描目录以查找某个值(例如 20.jpg-40.jpg)之间的文件名吗?PHP