2015-10-16 49 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

相關問題