Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python看门狗:有没有办法暂停观察者?_Python_Python 2.7_Watchdog - Fatal编程技术网

Python看门狗:有没有办法暂停观察者?

Python看门狗:有没有办法暂停观察者?,python,python-2.7,watchdog,Python,Python 2.7,Watchdog,我正在使用Watchdog监视一个目录,并使其与Dropbox保持同步 我面临的情况是,每当我从Dropbox下载一个文件时,我都会触发一个上载事件,因为我需要写入Watchdog正在监视的目录。这是我正在使用的代码 event_handler = UploadHandler.UploadHandler() observer = Observer() observer.schedule(event_handler, path=APP_PATH, recursive=True) observer.

我正在使用Watchdog监视一个目录,并使其与Dropbox保持同步

我面临的情况是,每当我从Dropbox下载一个文件时,我都会触发一个上载事件,因为我需要写入Watchdog正在监视的目录。这是我正在使用的代码

event_handler = UploadHandler.UploadHandler()
observer = Observer()
observer.schedule(event_handler, path=APP_PATH, recursive=True)
observer.start()

try:
    while True:
        # Apply download here   
        time.sleep(20)

except KeyboardInterrupt:
    observer.stop()

observer.join()

有没有办法在我应用下载时“暂停”观察者,并在完成后再次“取消暂停”观察者

您可以覆盖类
Observer
的方法
dispatch\u events
,以跳过不希望分派的事件。下面是一个如何执行此操作的示例:

class SkipObserver(watchdog.observers.Observer):
    def __init__(self, *args):
        Observer.__init__(self, *args)
        self._skip_list = []

    def skip(self, event):
        with self._lock:
            self._skip_list.append(event)

    def dispatch_events(self, event_queue, timeout):
        event, watch = event_queue.get(block=True, timeout=timeout)
        try:
            if event in self._skip_list:
                self._skip_list.remove(event)
            else:
                self._dispatch_event(event, watch)
        except KeyError:
            pass
        event_queue.task_done()
现在将示例中的
Observer
替换为
SkipObserver
,并使用
skip
方法跳过事件。注意不要在处理程序中使用
skip
,因为这将以死锁结束,
skip
在这里实现为阻塞。在处理事件时,观察者被锁定


如果要为每个处理程序指定跳过,可以使用与上面类似的方法。

我需要暂停功能,因此我使用以下观察者:

import time
import contextlib
import watchdog.observers


class PausingObserver(watchdog.observers.Observer):
    def dispatch_events(self, *args, **kwargs):
        if not getattr(self, '_is_paused', False):
            super(PausingObserver, self).dispatch_events(*args, **kwargs)

    def pause(self):
        self._is_paused = True

    def resume(self):
        time.sleep(self.timeout)  # allow interim events to be queued
        self.event_queue.queue.clear()
        self._is_paused = False

    @contextlib.contextmanager
    def ignore_events(self):
        self.pause()
        yield
        self.resume()
然后,我可以使用
pause()
resume()
方法直接暂停观察者,但我的主要使用案例是,当我只想忽略写入我正在监视的目录所引起的任何事件时,我使用上下文管理器:

import os
import datetime
import watchdog.events


class MyHandler(watchdog.events.FileSystemEventHandler):
    def on_modified(self, event):
        with OBSERVER.ignore_events():
            with open('./watchdir/modifications.log', 'a') as f:
                f.write(datetime.datetime.now().strftime("%H:%M:%S") + '\n')

if __name__ == '__main__':
    watchdir = 'watchdir'
    if not os.path.exists(watchdir):
        os.makedirs(watchdir)

    OBSERVER = PausingObserver()
    OBSERVER.schedule(MyHandler(), watchdir, recursive=True)
    OBSERVER.start()
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        OBSERVER.stop()
    OBSERVER.join()
您可以通过将两个代码块保存在一个文件中,运行它,并在创建的“watchdir”目录中添加/编辑/删除文件来测试这一点。修改的时间戳将附加到“watchdir/modifications.log”中


此功能,但该库仅在linux中工作,并且watchdog是独立于操作系统的

在花了大量时间(现在是早上5点,对任何打字错误和其他东西表示歉意)在这里给出了两个答案后,我觉得自己很愚蠢,并意识到一个更简单的解决方案可以满足我的需要

摘要(代码如下)

  • 我没有使用自定义观察者,但您可以
  • 确保事件处理程序与声明观察者的文件位于同一个文件中
  • 创建一个名为“暂停”或类似内容的
    全局
  • 在“已修改”上的
    内部或事件处理程序中使用的任何事件函数中,检查
    暂停是否为真
  • 如果为True,则退出,如果不是,则继续并暂停。完成后再继续
  • 将此项放在文件的顶部:

    global PAUSED
    PAUSED = False
    
    将其放入
    EventHandler.on\u modified()
    或您的事件处理程序以及您正在使用的事件函数中:

    # Retrieve global
    global PAUSED
    
    # If PAUSED, exit
    if PAUSED is True:
      return
    
    # If not, pause anything else from running and continue
    PAUSED = True
    
    # Do stuff here
    
    # Once finished, allow other things to run
    PAUSED = False
    

    推理:这将完全忽略暂停期间尝试运行的任何内容。我之所以需要它,是因为每次“文件修改”事件Watchdog最多会触发5次,因为文件仍在编写中。这确保了它只触发一次、暂停,并且在其他重复事件过期之前不会恢复。

    我遇到了一个类似的问题,正在研究Observer api以尝试解决它:我认为这将导致他丢失一些事件。我不认为OP可以丢失一些信号。@manu:如果你想在使用skip时丢失一些事件(因为它是阻塞的),它不会发生。