I am creating a watchdog in python where the user is able to select a folder to monitor. In order to use the selected watch directory I had to pass the variable into both my event handler and the scheduler. My result is below. The program first ask for the direcotry and avoids using any global variables.
WATCHDOG.py
import time
import logging
import tkinter as tk
from tkinter import filedialog
from watchdog.observers import Observer
from watchdog.events import LoggingEventHandler, FileSystemEventHandler
class OnMyWatch:
def __init__(self, dir):
self.observer = Observer()
self.dir = dir
def run(self):
event_handler = Handler()
self.observer.schedule(event_handler, self.dir, recursive = True)
self.observer.start()
try:
while True:
time.sleep(5)
except:
self.observer.stop()
print("Observer Stopped")
self.observer.join()
class Handler(FileSystemEventHandler):
def __init__(self, dir):
self.dir = dir
if __name__ == "__main__":
root = tk.Tk()
root.withdraw()
dir = filedialog.askdirectory()
watch = OnMyWatch(dir)
watch.run()
The direct answer is that any function or method in a module can read its global variables without doing anything special. As long as a function does not use a variable name is its parameter list or assign a value to a variable, it is not in the function namespace and python will look elsewhere for it (perhaps in a class namespace or the module namespace).
More to the point...
Looking at the docs on_any_event is not a static method and I don't see any advantage to making it static in your code. FileSystemEventHandler
is meant to be extended with the information you want for your event handling. Since you want the destination directory to be available in the handler, just create an initializer that puts it there.
I've done a bit of rearranging to put your script level code inside the if __name__=="__main__":
block and I've extended your classes to keep the data pulled in by the GUI. Now your obserser is decoupled from the GUI and whatever variables it happens to create. You could have more than one observer running in different threads and you could replace the GUI with something else (like a test script) if you'd like.
You can add other data to the classes, this is just the minimum to get your print to work.
import time
import logging
import tkinter as tk
from tkinter import filedialog
from watchdog.observers import Observer
from watchdog.events import LoggingEventHandler, FileSystemEventHandler
class OnMyWatch:
def __init__(self, watch_dir, dest_dir):
self.watch_dir = watch_dir
self.dest_dir = dest_dir
self.observer = Observer()
def run(self):
event_handler = Handler(self.dest_dir)
self.observer.schedule(event_handler, self.watch_dir, recursive = True)
self.observer.start()
try:
while True:
time.sleep(5)
except:
self.observer.stop()
print("Observer Stopped")
self.observer.join()
class Handler(FileSystemEventHandler):
def __init__(self, dest_dir):
self.dest_dir = dest_dir
def on_any_event(self, event):
print(self.dest_dir)
if __name__ == "__main__":
root = tk.Tk()
root.withdraw()
WATCH_DIRECTORY = filedialog.askdirectory()
WATCH_DESTINATION = filedialog.askdirectory()
watch = OnMyWatch(WATCH_DIRECTORY, WATCH_DESTINATION)
watch.run()
NOTE: Its okay to use global variables like you did on small scripts. The code above is written with future uses in mind, but really its over-designed for a simple script. Some people think that you shouldn't put more into code than than required because predictions about future use are often wrong.