2017-01-16 49 views
1

沿看門狗所以我有一個小腳本監視文件更改/修改,如果文件被更改它確實有它一堆東西,如:使用帶有Tkinter的

class Event(LoggingEventHandler): 
def dispatch(self, event): 
    #Do something here 

if __name__ == "__main__": 
    logging.basicConfig(level=logging.INFO, 
         format='%(asctime)s - %(message)s', 
         datefmt='%Y-%m-%d %H:%M:%S') 
    event_handler = Event() 
    observer = Observer() 
    observer.schedule(event_handler, my_path, recursive=True) 
    observer.start() 
    try: 
     while True: 
      time.sleep(1) 
    except KeyboardInterrupt: 
     observer.stop() 
    observer.join() 

而且它的偉大工程。但我有另一個腳本與一堆Tkinter小部件(典型的tk應用程序與mainloop())。現在,當用戶按下某個按鈕時,我想調用看門狗來監視像以前一樣的文件更改,並調用dispatch(),它會對其執行一些操作,並在同一腳本中更新一些tkinter UI控件,如progressbar。

對這個GUI的東西很新,不知道如何使看門狗循環和root.mainloop一起工作。如何做呢?

回答

5

看門狗運行在它自己的線程中,所以你沒有太多的工作要做。如果你想根據事件修改GUI,你應該設置一個線程安全隊列。 Tkinter小部件不應該被多於一個線程修改,所以常見模式是使用線程安全隊列來在線程之間進行通信。

以下示例將看守程序事件放置在隊列中,並且每當檢測到看門狗事件時使用event_generate將來自觀察者的信號發送到GUI。我不能絕對肯定地知道,以下內容可以在任何情況下都能正常工作,因爲我目前只能訪問一個linux盒子來測試它。但是,它似乎在linux上正常工作。

import Tkinter as tk 
from watchdog.observers import Observer 
from watchdog.events import FileSystemEventHandler 

from Queue import Queue 
import sys 

class CustomHandler(FileSystemEventHandler): 
    def __init__(self, app): 
     FileSystemEventHandler.__init__(self) 
     self.app = app 
    def on_created(self, event): app.notify(event) 
    def on_deleted(self, event): app.notify(event) 
    def on_modified(self, event): app.notify(event) 
    def on_moved(self, event): app.notify(event) 

class App(object): 
    def __init__(self): 
     path = sys.argv[1] if len(sys.argv) > 1 else "/tmp" 
     handler = CustomHandler(self) 
     self.observer = Observer() 
     self.observer.schedule(handler, path, recursive=True) 

     self.queue = Queue() 
     self.root = tk.Tk() 

     self.text = tk.Text(self.root) 
     self.text.pack(fill="both", expand=True) 

     self.text.insert("end", "Watching %s...\n" % path) 

     self.root.bind("<Destroy>", self.shutdown) 
     self.root.bind("<<WatchdogEvent>>", self.handle_watchdog_event) 

     self.observer.start() 

    def handle_watchdog_event(self, event): 
     """Called when watchdog posts an event""" 
     watchdog_event = self.queue.get() 
     print("event type:", type(watchdog_event)) 
     self.text.insert("end", str(watchdog_event) + "\n") 

    def shutdown(self, event): 
     """Perform safe shutdown when GUI has been destroyed""" 
     self.observer.stop() 
     self.observer.join() 

    def mainloop(self): 
     """Start the GUI loop""" 
     self.root.mainloop() 

    def notify(self, event): 
     """Forward events from watchdog to GUI""" 
     self.queue.put(event) 
     self.root.event_generate("<<WatchdogEvent>>", when="tail") 

app = App() 
app.mainloop()