python - 如何运行其函数可以作为线程调用的对象
问题描述
我正在用 Python 为 Raspberry Pi 编写脚本,其目的是监听服务器/消息代理的命令并使用某些硬件执行所述命令。有时,这些命令必须持续指定的持续时间(即我需要打开某些东西,保持 t 秒,然后关闭),这是通过让代码在 on 和 off 命令之间的所述持续时间内休眠来实现的(这发生在内部一个函数调用——hardware1.on(dur = t))。我希望能够用另一个命令中断该序列(例如在 t 秒结束之前关闭硬件)。我试图通过多处理来实现这一点,但无法获得我正在寻找的行为。
这个硬件(不同颜色的灯杆)是通过一个类 LiteStalk 控制的。此类由 Lite 对象(茎中的每个灯)组成,它们也有自己的类。这两个类都继承了 multiprocessing.process。在我创建特定 LiteStalk 然后侦听消息代理(基于 MQTT)的命令的主要代码中,我评估发布到代理的命令(这是在消息发布到代理时运行的 on_message 回调) .
import time
import LiteCntrlModule as LiteStalkMod
import multiprocessing
import paho.mqtt.client as mqtt
print('Starting...\n')
# Set gpio designatin mode to BCM
gpio.setmode(gpio.BCM)
# Initialize light stalk
stalkdict = {'red':1, 'yel':2, 'grn':3, 'bzr':4}
stalk = LiteStalkMod.LiteStalk(stalkdict)
msgRec = ""
def on_connect(client, userdata, flags, rc):
print("Connected with result code "+str(rc))
if(rc == 0):
print('Code "0" indicates successful connection. Waiting for messages...')
# Subscribing in on_connect() means that if we lose the connection and
# reconnect then subscriptions will be renewed.
client.subscribe("asset/andon1/state")
# The callback for when a PUBLISH message is received from the server.
def on_message(client, userdata, msg):
print(msg.topic+" "+str(msg.payload))
msgRec = msg.payload
eval(msg.payload)
if msg.payload == "stalk.off()":
print("If this executes while another command is running, it works!")
client = mqtt.Client(client_id="")
client.username_pw_set("mytopic", password="mypassword")
client.on_connect = on_connect
client.on_message = on_message
client.connect("mymessagebrokeraddress", 1883, 60)
client.subscribe("mytopic")
# Blocking call that processes network traffic, dispatches callbacks and
# handles reconnecting.
# Other loop*() functions are available that give a threaded interface and a
# manual interface.
try:
client.loop_start() # start listening in a thread and proceed
except KeyboardInterrupt: # so that aborting with Ctrl+C works cleanly
stalk.off()
finally:
stalk.shutDown()
LiteCtnrlModule(Lite 和 LiteStalk 类)如下:
import time
import multiprocessing
from relay_lib_seeed import *
Lite 类(多处理。进程):
# A Lite object has an associated relay and functions
# Ex: red
# A lite can be controlled
# Ex: red.blink()
def __init__(self, relayIn):
# Ex: red = Lite.Lite(1)
multiprocessing.Process.__init__(self) # allows you to create multiple objects that can be run as threads
self.daemon = True # creates a daemon thread that will exit when the main code terminates
self.start() # allows multiproc. to begin
self.relay = relayIn
def shutDown(self):
# terminates the threaded object
relay_off(self.relay)
self.join()
def off(self, dur = 0):
# turns light off
def on(self, dur = 0):
# turns light on, optional duration to stay on for
# blink
def blink(self, dur = 0, timeOn = .5, timeOff = .5):
# blinks light
LiteStalk 类(多处理。进程):
# A LiteStalk object can have any number of "lite" onjects in it. Ex:
# Object: stalk1
# A lite object in stalk1 respresents one segment/color of the light stalk
# stalk1.red
# Any lite can be turned on/off in various patterns for amounts of time, etc.
# stalk1.red.blink()
# An entire stalk can be controlled all at once
# stalk1.cycle()
liteList = {}
def __init__(self, liteListIn):
# liteListIn = {'clr1':relay1, 'clr2":relay2, 'clr3':relay3]...}
self.liteList = liteListIn;
multiprocessing.Process.__init__(self) # allows you to create multiple objects that can be run as threads
self.daemon = True # creates a daemon thread that will exit when the main code terminates
self.start() # allows multiproc. to begin
for lite in self.liteList: # for each lite color string in the lites dict
setattr(self, lite, Lite(self.liteList[lite])) # creates a lite obj attr in the LiteStalk obj
print(self.liteList)
def shutDown(self):
# each light is turned off and that gpio pin is cleaned-up
relay_all_off()
self.join() # joins thread
def off(self, dur = 0):
# turns all hardware off
def on(self):
# turns all hardware on, optional duration to stay on for
def blink(self, timeOn, timeOff):
# blinks all hardware
def cntDn(self, dur = 20, yelDur = 2, redDur = 10): #in min
# enters a count down sequence
该命令总是在执行发布到服务器的任何其他命令之前运行完成,即,在命令的持续时间内,茎保持打开状态,并且在持续时间结束之前不能被命令关闭(或其他任何东西)。我认为这可能是因为我没有在 run() 函数中包含我的多处理对象的所有功能,但我已经搞砸了,没有运气。
解决方案
我将建议在 threading.Event 或等效项上使用等待超时替换睡眠,然后检查睡眠何时结束,是否是由于设置了事件或超时。如果设置了事件,请停止。
但似乎除了可中断的睡眠之外还有其他问题。
推荐阅读
- fastapi - Tortoise 和 Fastapi 获取相关资源
- flutter - 如何在扫描条码时显示进度指示器
- python - pygame.sprite.LayeredUpdates.move_to_front() 不起作用
- javascript - 导入前过滤谷歌表格导入数据
- javascript - JSX 不接受三元语句(意外标记“?”)
- r - R从括号内的字符串中提取多个数字正则表达式
- sql - 我可以从 Terraform 脚本填充数据库吗(对于 GCP)
- google-kubernetes-engine - 带有自定义 SSL 证书的 Traefik 2.3 将不起作用
- python - 长度不匹配:预期轴有 0 个元素,新值有 6 个元素
- sql - 如何查找跨 JSON 数组存在重复值的行