如果我明白你正确地做什么,你想运行某些行为时,IP的可用性adderss您扫描更改。也就是说,当一个动作变为可用时(在关闭后)以及在其下降时(在可用后)执行一个不同的动作时,您想要执行一个动作。如果它继续做同样的事情,你不想做任何事情。
这要求你让你的函数访问某种state
变量。局部变量将不起作用,因为您从调度程序重复调用该函数(而不是编写自己的循环)。我认为有三个合理的选择。
最简单的(从当前代码需要改变多少的角度来看)是使用全局变量。像这样将工作:
import os, sys
import sched, time
state = None
def do_something(sc):
global state # global statement is required since we write to the global state
hostname = "192.168.254.102" #example
response = os.system("ping -c 1 " + hostname)
if response == 0 and state != "up":
state = "up"
print(hostname, 'is up!')
os.system("sudo python ../aquarium/nightlight_on.py 1")
os.system("omxplayer -o local ../music/jarvis_on.mp3 1")
elif state != "down":
state = "down"
print(hostname, 'is down!')
os.system("sudo python ../aquarium/nightlight_off.py 1")
sc.enter(160, 1, do_something, (sc,))
s = sched.scheduler(time.time, time.sleep)
s.enter(30, 1, do_something, (s,))
s.run()
全局变量通常被认为是不好的编程习惯,因为它们弄乱全局命名空间,尤其是在这样的情况下,当你将不会被访问,从任何其他代码state
变量。对于这样的小脚本来说并不是什么大事,但在更复杂的代码中这样做是一个坏主意。
下一个选择使用闭包来保存状态变量。闭包是内部函数可以访问的外部函数的名称空间。要写入闭包中的变量,您需要使用nonlocal
语句,就像前一版本代码中的global
语句一样(这只适用于您看起来像使用的Python 3):
import os, sys
import sched, time
def do_something_factory():
state = None # state is a local variable in the factory function's namespace
def do_something(sc):
nonlocal state # nonlocal statement lets us write to the outer scope
hostname = "192.168.254.102" #example
response = os.system("ping -c 1 " + hostname)
if response == 0 and state != "up":
state = "up"
print(hostname, 'is up!')
os.system("sudo python ../aquarium/nightlight_on.py 1")
os.system("omxplayer -o local ../music/jarvis_on.mp3 1")
elif state != "down":
state = "down"
print(hostname, 'is down!')
os.system("sudo python ../aquarium/nightlight_off.py 1")
sc.enter(160, 1, do_something, (sc,))
return do_something # return inner function to caller
s = sched.scheduler(time.time, time.sleep)
s.enter(30, 1, do_something_factory(), (s,)) # call factory function here!
s.run()
最后的办法是用class
来包含函数(作为方法)。状态将被存储在一个实例变量中,通过self
访问。主脚本代码将创建该对象,然后将绑定的方法传递给调度器。如果你愿意,你也许可以将部分或全部代码移入类中,但现在我会将设计保持不变。
import os, sys
import sched, time
class Doer(object):
def __init__(self):
self.state = None
def do_something(self, sc):
hostname = "192.168.254.102" #example
response = os.system("ping -c 1 " + hostname)
if response == 0 and self.state != "up":
self.state = "up"
print(hostname, 'is up!')
os.system("sudo python ../aquarium/nightlight_on.py 1")
os.system("omxplayer -o local ../music/jarvis_on.mp3 1")
elif self.state != "down":
self.state = "down"
print(hostname, 'is down!')
os.system("sudo python ../aquarium/nightlight_off.py 1")
sc.enter(160, 1, self.do_something, (sc,))
s = sched.scheduler(time.time, time.sleep)
d = Doer()
s.enter(30, 1, d.do_something, (s,))
s.run()
您好@Blckknght非常感谢您的回复。不幸的是,我正在运行python 2.7.3版本。我已经尝试过上面最简单的答案,但没有错误,但仍然是MP3循环...如果我将升级我的Python版本,会伤害我的系统吗? 由于我的python版本,这两个或你的答案有错误。错误是“NameError:全局名称'do_something'未定义 ” –
是的,Python 2不允许在中间解决方案中使用'nonlocal'语句。最后一个版本有一个拼写错误,如果你在'sc.enter'调用中添加'self',它应该可以工作(我已经编辑了上面的代码)。我不知道为什么你仍然在第一个版本上得到循环。它应该只在开始时调用一次'omxplayer'命令,然后每次系统在关闭后恢复一次。它打印出什么? – Blckknght