Search code examples
python-3.xtkinterpython-watchdog

combining tkinter and watchdog


I'm trying the following

  • Create a GUI with tkinter where the user will choose a directory to watch
  • Close the window
  • Pass the path to the directory to watchdog so it can watch for file changes

How does one go about combining both scripts into one app ?

This below post has a script which does nothing when I add a *.jpg file to my temp folder (osx). https://stackoverflow.com/a/41684432/11184726

Can someone point me towards a course or tutorial that will help me understand how to combine whats going on.

1. GUI :

from tkinter import *
from tkinter.filedialog import askopenfilename
from tkinter import filedialog

from tkinter.messagebox import showerror

globalPath = ""

class MyFrame(Frame):
    def __init__(self):
        Frame.__init__(self)
        self.master.title("Example")
        self.master.rowconfigure(5, weight=1)
        self.master.columnconfigure(5, weight=1)
        self.grid(sticky=W+E+N+S)

        self.button = Button(self, text="Browse", command=self.load_file, width=10)
        self.button.grid(row=1, column=0, sticky=W)

    def load_file(self):

        fname = askopenfilename(filetypes=(("Text File", "*.txt"),("All files", "*.*") ))
        global globalPath
        globalPath = fname
#         fname = askopenfilename(filetypes=(("Text File", "*.txt"),("All files", "*.*") ))
        if fname:
            try:
                print("""here it comes: self.settings["template"].set(fname)""")
                print (fname)
            except:                     # <- naked except is a bad idea
                showerror("Open Source File", "Failed to read file\n'%s'" % fname)
            return

if __name__ == "__main__":

    MyFrame().mainloop() # All above code will run inside window
print(__name__)
print("the path to the file is : " + globalPath)

2. Watchdog :

from watchdog.observers import Observer
from watchdog.events import PatternMatchingEventHandler

def on_created(event):
    # This function is called when a file is created
    print(f"hey, {event.src_path} has been created!")

def on_deleted(event):
    # This function is called when a file is deleted
    print(f"what the f**k! Someone deleted {event.src_path}!")

def on_modified(event):
    # This function is called when a file is modified
    print(f"hey buddy, {event.src_path} has been modified")
    #placeFile() #RUN THE FTP


def on_moved(event):
    # This function is called when a file is moved    
    print(f"ok ok ok, someone moved {event.src_path} to {event.dest_path}")




if __name__ == "__main__":



    # Create an event handler
    patterns = "*" #watch for only these file types "*" = any file
    ignore_patterns = ""
    ignore_directories = False
    case_sensitive = True

    # Define what to do when some change occurs 
    my_event_handler = PatternMatchingEventHandler(patterns, ignore_patterns, ignore_directories, case_sensitive)
    my_event_handler.on_created = on_created
    my_event_handler.on_deleted = on_deleted
    my_event_handler.on_modified = on_modified
    my_event_handler.on_moved = on_moved

    # Create an observer
    path = "."
    go_recursively = False # Will NOT scan sub directories for changes 

    my_observer = Observer()
    my_observer.schedule(my_event_handler, path, recursive=go_recursively)

    # Start the observer
    my_observer.start()
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        my_observer.stop()
    my_observer.join() 

Solution

  • Below is the proposed sample code to merge the two scripts (not exactly copy the two scripts into one, but showing the concept of what you request):

    from tkinter import *
    from tkinter import filedialog
    from watchdog.observers import Observer
    from watchdog.events import PatternMatchingEventHandler
    
    class Watchdog(PatternMatchingEventHandler, Observer):
        def __init__(self, path='.', patterns='*', logfunc=print):
            PatternMatchingEventHandler.__init__(self, patterns)
            Observer.__init__(self)
            self.schedule(self, path=path, recursive=False)
            self.log = logfunc
    
        def on_created(self, event):
            # This function is called when a file is created
            self.log(f"hey, {event.src_path} has been created!")
    
        def on_deleted(self, event):
            # This function is called when a file is deleted
            self.log(f"what the f**k! Someone deleted {event.src_path}!")
    
        def on_modified(self, event):
            # This function is called when a file is modified
            self.log(f"hey buddy, {event.src_path} has been modified")
    
        def on_moved(self, event):
            # This function is called when a file is moved    
            self.log(f"ok ok ok, someone moved {event.src_path} to {event.dest_path}")
    
    class GUI:
        def __init__(self):
            self.watchdog = None
            self.watch_path = '.'
            self.root = Tk()
            self.messagebox = Text(width=80, height=10)
            self.messagebox.pack()
            frm = Frame(self.root)
            Button(frm, text='Browse', command=self.select_path).pack(side=LEFT)
            Button(frm, text='Start Watchdog', command=self.start_watchdog).pack(side=RIGHT)
            Button(frm, text='Stop Watchdog', command=self.stop_watchdog).pack(side=RIGHT)
            frm.pack(fill=X, expand=1)
            self.root.mainloop()
    
        def start_watchdog(self):
            if self.watchdog is None:
                self.watchdog = Watchdog(path=self.watch_path, logfunc=self.log)
                self.watchdog.start()
                self.log('Watchdog started')
            else:
                self.log('Watchdog already started')
    
        def stop_watchdog(self):
            if self.watchdog:
                self.watchdog.stop()
                self.watchdog = None
                self.log('Watchdog stopped')
            else:
                self.log('Watchdog is not running')
    
        def select_path(self):
            path = filedialog.askdirectory()
            if path:
                self.watch_path = path
                self.log(f'Selected path: {path}')
    
        def log(self, message):
            self.messagebox.insert(END, f'{message}\n')
            self.messagebox.see(END)
    
    if __name__ == '__main__':
        GUI()