如何将附加参数传递给 FileSystemEventHandler class 以允许用户输入?
How to pass additional arguments to the FileSystemEventHandler class to allow for user input?
我正在 python 中创建一个看门狗,用户可以在其中 select 监视一个文件夹。为了使用 selected 监视目录,我必须将变量传递到我的事件处理程序和调度程序中。我的结果如下。该程序首先要求目录并避免使用任何全局变量。
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()
我可能不明白你的问题。你说的你想做的就是奏效。您的代码中的内容应该可以工作。您还可以使用 class-level 变量,它实际上也是一个全局变量,但位于特定 class 的命名空间中。此代码是一个更简单的示例,同时显示:
SOME_GLOBAL_VARIABLE = "Some Global Variable"
class Handler():
SOME_CLASS_LEVEL_VAR = "Some Class Level Var"
@staticmethod
def some_static_method(event):
print(SOME_GLOBAL_VARIABLE)
print(Handler.SOME_CLASS_LEVEL_VAR)
if __name__ == "__main__":
Handler.some_static_method({})
结果:
Some Global Variable
Some Class Level Var
我是不是漏掉了重点?如果我是,对此感到抱歉。
直接的答案是模块中的任何函数或方法都可以读取其全局变量而无需执行任何特殊操作。只要函数不使用变量名作为其参数列表或为变量赋值,它就不在函数命名空间中,python 将在别处寻找它(可能在 class命名空间或模块命名空间)。
更重要的是...
查看文档 on_any_event 不是静态方法,我看不出在您的代码中将其设为静态有任何优势。 FileSystemEventHandler
旨在扩展您想要用于事件处理的信息。由于您希望目标目录在处理程序中可用,只需创建一个将其放在那里的初始化程序。
我做了一些重新安排,将您的脚本级代码放在 if __name__=="__main__":
块中,并且我扩展了您的 classes 以保留 GUI 提取的数据。现在,您的观察者已与 GUI 以及它碰巧创建的任何变量分离。您可以在不同的线程中拥有多个观察者 运行,如果您愿意,您可以用其他东西(如测试脚本)替换 GUI。
您可以向 classes 添加其他数据,这只是让您的打印正常工作的最低要求。
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()
注意:可以像在小脚本中那样使用全局变量。上面的代码是为将来的用途而编写的,但对于一个简单的脚本来说,它实际上是 over-designed。有些人认为您不应该在代码中投入比要求更多的东西,因为对未来使用的预测通常是错误的。
我正在 python 中创建一个看门狗,用户可以在其中 select 监视一个文件夹。为了使用 selected 监视目录,我必须将变量传递到我的事件处理程序和调度程序中。我的结果如下。该程序首先要求目录并避免使用任何全局变量。
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()
我可能不明白你的问题。你说的你想做的就是奏效。您的代码中的内容应该可以工作。您还可以使用 class-level 变量,它实际上也是一个全局变量,但位于特定 class 的命名空间中。此代码是一个更简单的示例,同时显示:
SOME_GLOBAL_VARIABLE = "Some Global Variable"
class Handler():
SOME_CLASS_LEVEL_VAR = "Some Class Level Var"
@staticmethod
def some_static_method(event):
print(SOME_GLOBAL_VARIABLE)
print(Handler.SOME_CLASS_LEVEL_VAR)
if __name__ == "__main__":
Handler.some_static_method({})
结果:
Some Global Variable
Some Class Level Var
我是不是漏掉了重点?如果我是,对此感到抱歉。
直接的答案是模块中的任何函数或方法都可以读取其全局变量而无需执行任何特殊操作。只要函数不使用变量名作为其参数列表或为变量赋值,它就不在函数命名空间中,python 将在别处寻找它(可能在 class命名空间或模块命名空间)。
更重要的是...
查看文档 on_any_event 不是静态方法,我看不出在您的代码中将其设为静态有任何优势。 FileSystemEventHandler
旨在扩展您想要用于事件处理的信息。由于您希望目标目录在处理程序中可用,只需创建一个将其放在那里的初始化程序。
我做了一些重新安排,将您的脚本级代码放在 if __name__=="__main__":
块中,并且我扩展了您的 classes 以保留 GUI 提取的数据。现在,您的观察者已与 GUI 以及它碰巧创建的任何变量分离。您可以在不同的线程中拥有多个观察者 运行,如果您愿意,您可以用其他东西(如测试脚本)替换 GUI。
您可以向 classes 添加其他数据,这只是让您的打印正常工作的最低要求。
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()
注意:可以像在小脚本中那样使用全局变量。上面的代码是为将来的用途而编写的,但对于一个简单的脚本来说,它实际上是 over-designed。有些人认为您不应该在代码中投入比要求更多的东西,因为对未来使用的预测通常是错误的。