如何为Python辐射剂量计算代码添加键盘事件返回参数设置
实现键盘中断循环并返回参数输入阶段的解决方案
问题描述
我有一段通过公式计算辐射剂量的Python代码,需求是添加键盘事件以中断while True循环,返回到#DTU_01(start)处重新输入参数后继续计算。但添加keyboard库后无效果,仅能在输入框输入内容,代码如下:
import json from colorama import init, Fore, Style import keyboard import time init() with open("DTU.json", 'r') as file: data = json.load(file) print('Расчет дозы для трех установов ДТУ') a1_values = [float(data[dtu]['a1']) for dtu in data] b1_values = [float(data[dtu]['b1']) for dtu in data] a2_values = [float(data[dtu]['a2']) for dtu in data] a3_values = [float(data[dtu]['a3']) for dtu in data] b2_values = [float(data[dtu]['b2']) for dtu in data] b3_values = [float(data[dtu]['b3']) for dtu in data] print('DTU-01_1:') print('a1=', a1_values[0], 'b1=', b1_values[0], 'a2=', a2_values[0], 'b2=', b2_values[0], 'a3=', a3_values[0], 'b3=', b3_values[0]) print('DTU-01_2:') print('a1=', a1_values[1], 'b1=', b1_values[1], 'a2=', a2_values[1], 'b2=', b2_values[1], 'a3=', a3_values[1], 'b3=', b3_values[1]) print('DTU-01_3:') print('a1=', a1_values[2], 'b1=', b1_values[2], 'a2=', a2_values[2], 'b2=', b2_values[2], 'a3=', a3_values[2], 'b3=', b3_values[2]) k_sens1 = [1.5, 1.2245, 1, 0.8163, 0.6666, 0.5442, 0.4444] k_sens2 = [1.4964, 1.2239, 1, 0.8167, 0.6678, 0.5459, 0.4461] k_sens3 = [1.4948, 1.2236, 1, 0.8169, 0.6682, 0.54665, 0.4471] # DTU-1(start) dtu = int(input("Номер ДТУ = ")) if dtu == 1: a_m = [float(a1_values[0]), float(a2_values[0]), float(a3_values[0])] b_m = [float(b1_values[0]), float(b2_values[0]), float(b3_values[0])] b = b_m[0] a = a_m[0] k = k_sens1 elif dtu == 2: a_m = [float(a1_values[1]), float(a2_values[1]), float(a3_values[1])] a = a_m[0] b_m = [float(b1_values[1]), float(b2_values[1]), float(b3_values[1])] b = b_m[0] k = k_sens2 else: a_m = [float(a1_values[2]), float(a2_values[2]), float(a3_values[2])] a = a_m[0] b_m = [float(b1_values[2]), float(b2_values[2]), float(b3_values[2])] b = b_m[0] k = k_sens3 # DTU-1(end) # KdrDf(start) n = int(input("K_group = ")) ks = k[n] # Correct index for ks k_dr = float(input('K_dreif = ')) dfon = float(input("Dfon = ")) # KdrDf(end) while True: i1_str = input("I1 = ") i2_str = input("I2 = ") if ',' in i1_str: i1_str = i1_str.replace(',', '.') if ',' in i2_str: i2_str = i2_str.replace(',', '.') i_1 = float(i1_str) i_2 = float(i2_str) i1 = i_1 * ks i2 = i_2 * ks d1 = (k_dr * i1 * a) + b d2 = (k_dr * i2 * a) + b D = ((d1 + d2) / 2) - dfon if 1.5 <= D < 15: a = a_m[1] b = b_m[1] d1 = (k_dr * i1 * a) + b d2 = (k_dr * i2 * a) + b D = ((d1 + d2) / 2) - dfon print(f"{Fore.YELLOW}{round(D, 3)}{Style.RESET_ALL}") elif D >= 15: a = a_m[2] b = b_m[2] d1 = (k_dr * i1 * a) + b d2 = (k_dr * i2 * a) + b D = ((d1 + d2) / 2) - dfon print(f"{Fore.RED}{round(D, 3)}{Style.RESET_ALL}") else: print(f"{Fore.GREEN}{round(D, 3)}{Style.RESET_ALL}")
问题原因
原代码中input()是阻塞式调用,程序会卡在输入等待状态,主线程被占用,导致keyboard库的事件监听无法正常响应。
修改方案
通过外层循环包裹参数输入逻辑,在计算循环中轮询键盘按键状态,实现中断返回功能:
import json from colorama import init, Fore, Style import keyboard import time init() with open("DTU.json", 'r') as file: data = json.load(file) print('Расчет дозы для трех установов ДТУ') a1_values = [float(data[dtu]['a1']) for dtu in data] b1_values = [float(data[dtu]['b1']) for dtu in data] a2_values = [float(data[dtu]['a2']) for dtu in data] a3_values = [float(data[dtu]['a3']) for dtu in data] b2_values = [float(data[dtu]['b2']) for dtu in data] b3_values = [float(data[dtu]['b3']) for dtu in data] print('DTU-01_1:') print('a1=', a1_values[0], 'b1=', b1_values[0], 'a2=', a2_values[0], 'b2=', b2_values[0], 'a3=', a3_values[0], 'b3=', b3_values[0]) print('DTU-01_2:') print('a1=', a1_values[1], 'b1=', b1_values[1], 'a2=', a2_values[1], 'b2=', b2_values[1], 'a3=', a3_values[1], 'b3=', b3_values[1]) print('DTU-01_3:') print('a1=', a1_values[2], 'b1=', b1_values[2], 'a2=', a2_values[2], 'b2=', b2_values[2], 'a3=', a3_values[2], 'b3=', b3_values[2]) k_sens1 = [1.5, 1.2245, 1, 0.8163, 0.6666, 0.5442, 0.4444] k_sens2 = [1.4964, 1.2239, 1, 0.8167, 0.6678, 0.5459, 0.4461] k_sens3 = [1.4948, 1.2236, 1, 0.8169, 0.6682, 0.54665, 0.4471] # 外层循环:控制重新输入参数的流程 while True: # DTU-1(start) dtu = int(input("Номер ДТУ = ")) if dtu == 1: a_m = [float(a1_values[0]), float(a2_values[0]), float(a3_values[0])] b_m = [float(b1_values[0]), float(b2_values[0]), float(b3_values[0])] b = b_m[0] a = a_m[0] k = k_sens1 elif dtu == 2: a_m = [float(a1_values[1]), float(a2_values[1]), float(a3_values[1])] a = a_m[0] b_m = [float(b1_values[1]), float(b2_values[1]), float(b3_values[1])] b = b_m[0] k = k_sens2 else: a_m = [float(a1_values[2]), float(a2_values[2]), float(a3_values[2])] a = a_m[0] b_m = [float(b1_values[2]), float(b2_values[2]), float(b3_values[2])] b = b_m[0] k = k_sens3 # DTU-1(end) # KdrDf(start) n = int(input("K_group = ")) ks = k[n] # Correct index for ks k_dr = float(input('K_dreif = ')) dfon = float(input("Dfon = ")) # KdrDf(end) print("开始计算,按Esc键返回参数输入阶段") # 计算循环:处理剂量计算逻辑 while True: # 检查是否按下Esc键,触发返回参数输入 if keyboard.is_pressed('esc'): print("\n已触发返回,重新输入参数...") # 等待按键松开,避免连续触发 while keyboard.is_pressed('esc'): time.sleep(0.1) break # 输入I1并检查按键 i1_str = input("I1 = ") if keyboard.is_pressed('esc'): print("\n已触发返回,重新输入参数...") while keyboard.is_pressed('esc'): time.sleep(0.1) break # 输入I2并检查按键 i2_str = input("I2 = ") if keyboard.is_pressed('esc'): print("\n已触发返回,重新输入参数...") while keyboard.is_pressed('esc'): time.sleep(0.1) break # 处理输入的逗号转点 if ',' in i1_str: i1_str = i1_str.replace(',', '.') if ',' in i2_str: i2_str = i2_str.replace(',', '.') # 处理非数字输入异常 try: i_1 = float(i1_str) i_2 = float(i2_str) except ValueError: print("输入无效,请输入数字") continue # 剂量计算逻辑 i1 = i_1 * ks i2 = i_2 * ks d1 = (k_dr * i1 * a) + b d2 = (k_dr * i2 * a) + b D = ((d1 + d2) / 2) - dfon if 1.5 <= D < 15: a = a_m[1] b = b_m[1] d1 = (k_dr * i1 * a) + b d2 = (k_dr * i2 * a) + b D = ((d1 + d2) / 2) - dfon print(f"{Fore.YELLOW}{round(D, 3)}{Style.RESET_ALL}") elif D >= 15: a = a_m[2] b = b_m[2] d1 = (k_dr * i1 * a) + b d2 = (k_dr * i2 * a) + b D = ((d1 + d2) / 2) - dfon print(f"{Fore.RED}{round(D, 3)}{Style.RESET_ALL}") else: print(f"{Fore.GREEN}{round(D, 3)}{Style.RESET_ALL}")
关键修改点
- 新增外层循环:将参数输入和计算逻辑包裹在一个外层
while True循环中,中断计算循环后会自动回到参数输入步骤。 - 键盘按键轮询:在计算循环的每次迭代中,用
keyboard.is_pressed('esc')检查按键状态,输入前后都加入检查,确保在输入过程中也能触发返回。 - 按键防抖处理:触发返回后等待按键松开,避免连续触发多次。
- 输入异常处理:添加
try-except捕获非数字输入,防止程序崩溃。
内容的提问来源于stack exchange,提问作者plkh_20
相关产品推荐
相关产品推荐

