问题描述
我在 Raspbian 中有一个 python 脚本,它无限循环并在主函数执行之间休眠 15 分钟。 Main 是线程化的,但通常需要 3 秒才能运行。我不希望任何代码中断,及时进行下一次调用。在睡眠期间,我想检测按键 'r' 以选择性地启动另一个 func,也可能是线程化的。
我尝试了 pynput 模块,但出现了奇怪的暂停,这似乎与线程处理和使用 VNC 签入有关,这是我需要的。我还在线程中尝试了常规的旧输入,但在没有用户输入的情况下无法结束线程。
键盘模块在 Windows 中运行良好,但没有检测到 Raspbian 的按键。我正在使用 sudo "sudo python3 scriptname.py" 运行脚本我并不在乎是否通过使用线程即时检测密钥。如果需要,我可以在一分钟左右后切断我的睡眠周期以调用该函数。我只是不能有很大的停顿。
import time
import keyboard
import threading
def mainFunc():
print('does stuff')
def keyFunc():
print('do key detect stuff')
while True:
t1 = threading.Thread(target=mainFunc)
t1.start()
time.sleep(60)
t1.join()
keyboard.on_press_key("r",lambda _:keyFunc())
for _ in range(14):
time.sleep(60)
keyboard.unhook_all()
解决方法
我认为有帮助的一种方法是从 datetime 对象创建一个时间跨度持续时间,并将其用于主循环。
这是我创建的示例。希望对您的 pi raspbian 脚本有所帮助。
from datetime import *
import time
import keyboard
import threading
#every 3 second function
x_start = datetime.now()
xSleep=3
def mainFunc():
newTime = datetime.now()
if(getTimeDiff(x_start,newTime)>xSleep):
setXStart(datetime.now())
return True
#every 15 minute function
y_start = datetime.now()
ySleep=900
def fifteenMinuteFunction():
newTime = datetime.now()
if(getTimeDiff(y_start,newTime)>ySleep):
setYStart(datetime.now())
return True
#key press function (from pressing p)
def keyFunc():
print("do keystuff")
#calculate time difference since last call
def getTimeDiff(start,end):
span = end - start
#convert to string
spanStr = str(span)[0:7]
hours = spanStr[0:1]
minutes = spanStr[2:4]
seconds = spanStr[5:7]
#convert to rounded int (seconds)
seconds = int(seconds) + (int(minutes) * 60) + (int(hours) * 60 * 60)
return int(seconds)
#set new start time for 3 second function
def setXStart(newTime):
global x_start
x_start = newTime
#set new start tiem for 15 minute function
def setYStart(newTime):
global y_start
y_start = newTime
#bind keyboard keys
keyboard.on_press_key("p",lambda _:keyFunc()) # p do stuff function
while True:
if keyboard.is_pressed('x'): # exit keybind to x
exit()
elif mainFunc():
print("Doing thingy every "+str(xSleep)+" seconds") # 3 seconds
elif fifteenMinuteFunction():
print("Doing thingy every "+str(ySleep)+" seconds") # 15 mins
else:
time.sleep(.1)
输出:
do keystuff
doing thingy every 3 seconds
do keystuff
doing thingy every 3 seconds
doing thingy every 3 seconds
....
doing thingy every 900 seconds
...
,
def inputDaemon():
while True:
x = input('r to reload')
if x == 'r': doTheFunc()
inpD = threading.Thread(target=inputDaemon)
inpD.daemon = True
inpD.start()
我最终使用的并且运行良好。