2015-10-16 25 views
0

我在这里有以下代码。我想要做的是我想脚本来扫描我的IP地址,然后做一定的工作。IP扫描然后做某些工作,只播放一次MP3

我的问题是,即使我没有关闭我的手机WIFI,它携带主机名的IP,MP3总是每30秒重复一次。

我希望MP3只能在脚本找到IP后播放一次,但扫描将继续扫描。

这可能吗?任何帮助将是非常赞赏

#!/usr/bin/env python 
import os, sys 
import sched, time 
s = sched.scheduler(time.time, time.sleep) 
def do_something(sc): 
     import os 
     hostname = "192.168.254.102" #example 
     response = os.system("ping -c 1 " + hostname) 
     if response == 0: 
       print(hostname, 'is up!') 
       os.system("sudo python ../aquarium/nightlight_on.py 1") 
       os.system("omxplayer -o local ../music/jarvis_on.mp3 1") 
     else: 
       print(hostname, 'is down!') 
       os.system("sudo python ../aquarium/nightlight_off.py 1") 
     sc.enter(160, 1, do_something, (sc,)) 
s.enter(30, 1, do_something, (s,)) 
s.run() 

回答

1

如果我明白你正确地做什么,你想运行某些行为时,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() 
+0

您好@Blckknght非常感谢您的回复。不幸的是,我正在运行python 2.7.3版本。我已经尝试过上面最简单的答案,但没有错误,但仍然是MP3循环...如果我将升级我的Python版本,会伤害我的系统吗? 由于我的python版本,这两个或你的答案有错误。错误是“NameError:全局名称'do_something'未定义 ” –

+0

是的,Python 2不允许在中间解决方案中使用'nonlocal'语句。最后一个版本有一个拼写错误,如果你在'sc.enter'调用中添加'self',它应该可以工作(我已经编辑了上面的代码)。我不知道为什么你仍然在第一个版本上得到循环。它应该只在开始时调用一次'omxplayer'命令,然后每次系统在关闭后恢复一次。它打印出什么? – Blckknght

相关问题