python - 如何在函数内部无限循环
问题描述
我在编写将与 MQTT 服务器通信并检查我可以使用本地网页控制的 GPIO 引脚的实际状态的代码时遇到问题(我仍在学习)。
我的问题是我不知道如何在函数内部进行无限循环,该函数将检查引脚的实际状态并将其与 MQTT 发送的最后状态进行比较,如果有变化,它将向 MQTT 发布新值。
#!/usr/bin/env python2
import paho.mqtt.client as mqtt
import urllib
from time import sleep
import RPi.GPIO as GPIO
#Conf GPIO Number for relays
out_1 = 6
#Conf MQTT broker
broker_ip = "192.168.1.34"
broker_port = 1883
broker_timeout = 60
topic_sub = "/printer/#"
topic_out1 = "/printer/onoff"
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(out_1, GPIO.OUT)
GPIO.output(out_1, GPIO.HIGH)
def main():
# This is the issue part where I wanted to make looped check for actual value
def check_state(astate):
f= open("/sys/class/gpio/gpio6/value","r")
if f.mode == "r":
state = f.read(1)
if astate == state :
return
else:
print("CHANGE")
def on_connect(client, userdata, flags, rc):
client.subscribe(topic_sub)
def on_message(client, userdata, msg):
if msg.topic == topic_out1 :
if msg.payload == "1" :
GPIO.output(out_1, GPIO.LOW)
state = "1"
sleep(.1)
print("OUT 1 ON")
if msg.payload == "0" :
GPIO.output(out_1, GPIO.HIGH)
state = "0"
sleep(.1)
print("OUT 1 OFF")
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect(broker_ip, broker_port, broker_timeout)
client.loop_forever()
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
GPIO.cleanup()
编辑:这就是我在@MilkyWay90 的多处理帮助下做到的。
#!/usr/bin/env python2
import urllib
from multiprocessing import Process
from time import sleep
import RPi.GPIO as GPIO
#Conf GPIO Number for relays
out_1 = 6
#Conf MQTT broker
broker_ip = "192.168.1.34"
broker_port = 1883
broker_timeout = 60
topic_sub = "/printer/#"
topic_out1 = "/printer/onoff"
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(out_1, GPIO.OUT)
GPIO.output(out_1, GPIO.HIGH)
def check_state():
import paho.mqtt.client as mqtt
clientSEND = mqtt.Client()
clientSEND.connect(broker_ip, broker_port, broker_timeout)
while True:
faf= open("/sys/class/gpio/gpio6/value","r")
qf= open("/home/pi/.state","r")
fastate = faf.read(1)
#reverse logic for gpio value
if fastate == "0" :
astate = "1"
elif fastate == "1" :
astate = "0"
qstate = qf.read(1)
#print("GPIO state: ",astate,"MQTT state: ",qstate)
if astate != qstate :
clientSEND.publish(topic_out1, astate)
#print("CHANGE")
sleep(3)
else:
sleep(3)
def mqtt():
import paho.mqtt.client as mqtt
def on_connect(client, userdata, flags, rc):
client.subscribe(topic_sub)
def on_message(client, userdata, msg):
if msg.topic == topic_out1 :
if msg.payload == "1" :
GPIO.output(out_1, GPIO.LOW)
state_write("1")
sleep(.1)
#print("OUT 1 ON")
if msg.payload == "0" :
GPIO.output(out_1, GPIO.HIGH)
state_write("0")
sleep(.1)
#print("OUT 1 OFF")
def state_write(state):
f= open("/home/pi/.state","w")
f.write(state)
f.close
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect(broker_ip, broker_port, broker_timeout)
client.loop_forever()
if __name__ == "__main__":
try:
bck_statuscheck = Process(target=check_state)
mqtt_process = Process(target=mqtt)
bck_statuscheck.start()
mqtt_process.start()
bck_statuscheck.join()
mqtt_process.join()
except KeyboardInterrupt:
GPIO.cleanup()
解决方案
您可以使用while 循环。
while 循环是 Python 中的一个循环,它在条件计算为True时运行指定的代码。
这是一个while循环的结构:
while <condition>:
CODE
一个例子可能是:
counter = 1 # Declare a variable named "counter" and set it to the integer 1
while counter <= 10: # This is the while loop. As you can see, the condition checks whether the counter is less than or equal to the integer 10. If it is, execute the code that is indented. This will be checked every iteration
print(counter) # Use the print function to print out the counter with a newline
counter += 1 # Increment the counter. This is roughly equivalent to counter = counter + 1
这输出:
1
2
3
4
5
6
7
8
9
10
您可以简单地将 while 语句修改为 ALWAYS evalulate 为 True:
counter = 1
while True:
print(counter)
counter += 1
这确实在函数中起作用。
def print_natural_numbers():
counter = 1
while True:
print(counter)
counter += 1
print_natural_numbers()
要根据您的需要修改上述内容:
def check_state(astate):
while True:
f= open("/sys/class/gpio/gpio6/value","r")
if f.mode == "r":
state = f.read(1)
if astate == state :
return
else:
print("CHANGE")
或者另一种选择:
while True:
check_state(...)
编辑:
在这之后不会一直停留在一个功能中吗?所以它只会检查实际状态但忽略其他一切(MQTT部分)?
(改写:使用上面的代码,这将一直运行(因为 while 循环),而不是继续到其他代码)
看起来这需要multiprocessing。
一个示范:
from multiprocessing import Process
def print_natural_numbers():
counter = 1
while True:
print(counter, flush = True)
counter += 1
def print_square_numbers():
counter = 1
while True:
print(counter ** 2, flush = True)
counter += 1
if __name__ == '__main__':
nat_numbers = Process(target=print_natural_numbers)
sqrt_numbers = Process(target=print_square_numbers)
sqrt_numbers.start()
nat_numbers.start()
sqrt_numbers.join()
nat_numbers.join()
对于您的情况,您需要创建两个函数:检查函数和代表其他所有内容的函数。
推荐阅读
- html - 居中带边距的全屏 div
- javascript - 优化哈希表实现以容纳大量元素
- loops - 批处理文件跳过 FOR LOOP
- cordova - 用于向 iOS SDK 发送面包屑信息的 Cordova 插件
- wordpress - 没有收到从我的服务器以表单形式发送的电子邮件 - wordpress 网站
- php - 如果我退出管理员帐户,Wordpress 菜单栏不显示
- regex - 如何改进基于正则表达式的单元格替换以每行操作而不是需要遍历每个单元格?
- asp.net - 使用 SQL Server 身份验证对 ASP.NET Web API 进行身份验证
- ruby-on-rails - 使用 Rails 验证,如何将短语列入白名单,例如“Learn Ruby”
- python - “NoneType”对象没有属性“月”