2014-12-24 69 views
3

我想学习python-watchdog,但我有点困惑为什么我设置的工作运行不止一次。所以,这里是我的设立:python看门狗运行不止一次

#handler.py 
import os 
from watchdog.events import FileSystemEventHandler 
from actions import run_something 

def getext(filename): 
    return os.path.splitext(filename)[-1].lower() 

class ChangeHandler(FileSystemEventHandler): 

    def on_any_event(self, event): 

     if event.is_directory: 
      return 
     if getext(event.src_path) == '.done': 
      run_something() 
     else: 
      print "event not directory.. exiting..." 
      pass 

观察者设置像这样:

#observer.py 
import os 
import time 
from watchdog.observers import Observer 
from handler import ChangeHandler 

BASEDIR = "/path/to/some/directory/bin" 

def main(): 

    while 1: 

     event_handler = ChangeHandler() 
     observer = Observer() 
     observer.schedule(event_handler, BASEDIR, recursive=True) 
     observer.start() 
     try: 
      while True: 
       time.sleep(1) 
     except KeyboardInterrupt: 
      observer.stop() 
     observer.join() 

if __name__ == '__main__': 
    main() 

最后,像这样的动作:

#actions.py 
import os 
import subprocess 

def run_something(): 
    output = subprocess.check_output(['./run.sh']) 
    print output 
    return None 

..where ./run.sh是只是一个shell脚本,我想运行时发现一个扩展名为.done的文件/path/to/some/directory/bin

#run.sh 
#!/bin/bash 
echo "Job Start: $(date)" 
rm -rf /path/to/some/directory/bin/job.done # remove the .done file 
echo "Job Done: $(date)" 

然而,当我发出python observer.py,然后做一个/path/to/some/directory/bintouch job.done,我看到我的shell脚本./run.sh运行三次,而不是一个..

我很困惑,为什么这个运行三次,不只是一次(我删除了我的bash脚本中的job.done文件)

+1

'虽然1'和'虽然是真的'是不好的代码,并且即时猜测你的代码,它甚至没有必要,因为'连接'调用通常阻塞直到条件满足。你的代码会在某个时候无限期地被阻塞,从而创建一个浪费系统资源的僵尸进程 – specializt

+0

实际上,我直接从教程中取出代码:http://ginstrom.com/scribbles/2012/05/10/continuous-integration- in-python-using-watchdog /我现在已经从代码中删除了'while 1'和'While true'。再次感谢提示。 – JohnJ

回答

3

要调试看门狗脚本,打印什么看门狗作为事件看到是很有用的。一个文件编辑或CLI命令(如touch)可能导致多个看门狗事件。例如,如果您插入打印语句:

class ChangeHandler(FileSystemEventHandler): 

    def on_any_event(self, event): 
     print(event) 

记录每一个事件,运行

% touch job.done 

产生

2014-12-24 13:11:02 - <FileCreatedEvent: src_path='/home/unutbu/tmp/job.done'> 
2014-12-24 13:11:02 - <DirModifiedEvent: src_path='/home/unutbu/tmp'> 
2014-12-24 13:11:02 - <FileModifiedEvent: src_path='/home/unutbu/tmp/job.done'> 

上面有两个事件与src_path在结尾job.done。因此,

if getext(event.src_path) == '.done': 
     run_something() 

运行两次,因为有一个FileCreatedEventFileModifiedEvent。 你可能最好只监测FileModifiedEvent s。

+0

这就是真棒 - 非常感谢 - 我现在使用'on_created'来监视新创建的文件(因为我在我的bash脚本中删除了'job.done')。按预期工作!接受你的回答:) – JohnJ

+0

你认为我更适合寻找'FileCreatedEvent'而不是'FileModifiedEvent'吗? – JohnJ

+0

嗯,我认为这不重要。我建议'FileModifiedEvent'只是因为它最后发生,所以你知道写入文件的任何东西都已经写好了。在这种情况下,听起来好像你没有阅读文件,所以没关系。 – unutbu