Python,使用多线程退出带有用户输入的 While 循环(ctrl+c 不起作用)
Python, exit While loop with User Input using multithreading (cntrl+c wont work)
我有一个系统利用率函数,monitor(),我想 运行 直到用户通过输入数字零 exit_collecting() 来停止它。我不想突然结束程序,因为那样会否定后续代码。
我尝试 运行 使用多线程 exit_collecting() 和 monitor() 来连接这两个函数,让 monitor() 运行 直到用户通过键入零停止它,exit_collecting( ).
我下面的代码抛出了一堆回溯。我是这方面的新手,任何想法,任何帮助都会很棒。谢谢你。顺便说一句,我最初尝试使用“尝试使用 KeyboardInterrupt 除外”,但是当使用 IDLE (Spyder) 时,ctrl-c 组合不起作用(它分配给“复制”),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()
你的多进程版本注定要失败,因为每个进程都有自己的内存space并且不共享相同的变量flag
。它可以通过多处理来完成,但您必须使用使用共享内存的 flag
的实现。
使用线程的解决方案要简单得多,只要进行一处更改,您的代码就应该可以正常工作。您忽略了将 flag
声明为全局。这是确保函数 exit_collecting
和 monitor
修改同一个变量所必需的。如果没有这些声明,每个函数都会修改一个 local 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
线程变成daemon线程来简化上面的代码,也就是当所有非daemon都自动终止的线程线程终止(如当前所写,函数 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
我有一个系统利用率函数,monitor(),我想 运行 直到用户通过输入数字零 exit_collecting() 来停止它。我不想突然结束程序,因为那样会否定后续代码。
我尝试 运行 使用多线程 exit_collecting() 和 monitor() 来连接这两个函数,让 monitor() 运行 直到用户通过键入零停止它,exit_collecting( ).
我下面的代码抛出了一堆回溯。我是这方面的新手,任何想法,任何帮助都会很棒。谢谢你。顺便说一句,我最初尝试使用“尝试使用 KeyboardInterrupt 除外”,但是当使用 IDLE (Spyder) 时,ctrl-c 组合不起作用(它分配给“复制”),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()
你的多进程版本注定要失败,因为每个进程都有自己的内存space并且不共享相同的变量flag
。它可以通过多处理来完成,但您必须使用使用共享内存的 flag
的实现。
使用线程的解决方案要简单得多,只要进行一处更改,您的代码就应该可以正常工作。您忽略了将 flag
声明为全局。这是确保函数 exit_collecting
和 monitor
修改同一个变量所必需的。如果没有这些声明,每个函数都会修改一个 local 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
线程变成daemon线程来简化上面的代码,也就是当所有非daemon都自动终止的线程线程终止(如当前所写,函数 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