Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/288.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.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 跳过fsevents队列中的步骤_Python_Callback_Fsevents_Python Watchdog - Fatal编程技术网

Python 跳过fsevents队列中的步骤

Python 跳过fsevents队列中的步骤,python,callback,fsevents,python-watchdog,Python,Callback,Fsevents,Python Watchdog,我当前正在使用fsevents监视文件夹。每次添加文件时,都会在此文件上执行代码。每秒会向文件夹中添加一个新文件 从fsevents导入观察者,流 def文件事件回调(事件): #用于将文件添加到文件夹的代码256 如果event.mask==256: fileChanged=event.name #使用文件更改的文件执行操作 如果名称=“\uuuuu main\uuuuuuuu”: 观察者=观察者() observer.start() stream=stream(文件事件回调,'folder'

我当前正在使用fsevents监视文件夹。每次添加文件时,都会在此文件上执行代码。每秒会向文件夹中添加一个新文件

从fsevents导入观察者,流
def文件事件回调(事件):
#用于将文件添加到文件夹的代码256
如果event.mask==256:
fileChanged=event.name
#使用文件更改的文件执行操作
如果名称=“\uuuuu main\uuuuuuuu”:
观察者=观察者()
observer.start()
stream=stream(文件事件回调,'folder',文件事件=True)
观察员附表(溪流)
观察员加入
这很有效。唯一的问题是,库正在为添加到文件夹中的每个文件构建一个队列。在file\u event\u回调中执行的代码可能需要一秒钟以上的时间。发生这种情况时,应跳过队列中的其他项,以便只使用最新的项

如何从队列中跳过项目,以便在最后一个项目完成后,只向使用的文件夹添加最新的项目


我首先尝试使用watchdog,但由于它必须在mac上运行,所以我在使它按我想要的方式工作时遇到了一些困难

我不知道您使用的是什么库,当您说“这是在构建队列…”时,我不知道您指的是什么“这”…但一个明显的答案是将您自己的库放在它使用的任何库前面,这样您就可以直接操纵该队列。例如:

import queue
import threading

def skip_get(q):
    value = q.get(block=True)
    try:
        while True:
            value = q.get(block=False)
    except queue.Empty:
        return value

q = queue.Queue()

def file_event_callback(event):
    # code 256 for adding file to folder
    if event.mask == 256:
        fileChanged = event.name
        q.put(fileChanged)

def consumer():
    while True:
        fileChanged = skip_get(q)
        if fileChanged is None:
            return
        # do stuff with fileChanged
现在,在启动观察者之前,请执行以下操作:

t = threading.Thread(target=consumer)
t.start()
最后:

observer.join()
q.put(None)
t.join()

那么,这是如何工作的呢

首先,让我们看看消费者方面。当您调用
q.get()
时,这会从队列中弹出第一个内容。但是如果什么都没有呢?这就是
参数的作用。如果为false,则
get
将引发
队列。Empty
异常。如果这是真的,
get
将永远等待(以线程安全的方式),直到出现弹出的内容。因此,通过阻塞一次,我们可以处理没有任何内容可读取的情况。然后在不阻塞的情况下循环,我们消耗队列中的任何其他内容,以处理有太多内容无法读取的情况。因为我们不断地将
重新分配给我们弹出的任何对象,所以我们最终得到的是放在队列上的最后一件东西

现在,让我们看看制作人方面。当您调用
q.put(value)
时,这只会将
value
放入队列。除非您对队列设置了大小限制(我没有),否则这是无法阻止的,所以您不必担心任何问题。但是现在,你如何向消费者发出你已经完成的信号?它将永远在
q.get(block=True)
中等待;唤醒它的唯一方法是给它一些弹出的值。通过按下sentinel值(在本例中,
None
很好,因为它作为文件名无效),并通过退出让消费者处理
None
,我们为自己提供了一种良好、干净的关机方式。(因为我们从不在
None
之后推送任何内容,所以不可能意外跳过它。)因此,我们可以只推
None
,然后确保(排除任何其他错误)使用者线程最终将退出,这意味着我们可以执行
t.join()
等待,直到它退出,而不必担心死锁


我在上面提到过,你可以用一个。如果你想一想队列实际上是如何工作的,它只是一个受条件保护的列表(或deque,或任何东西):消费者等待条件,直到有可用的东西,而生产者通过将它添加到列表中并发出条件信号,使它可用。如果您只想要最后一个值,那么实际上没有理由列出它。因此,您可以这样做:

class OneQueue(object):
    def __init__(self):
        self.value = None
        self.condition = threading.Condition()
        self.sentinel = object()
    def get(self):
        with self.condition:
            while self.value is None:
                self.condition.wait()
            value, self.value = self.value, None
            return value
    def put(self, value):
        with self.condition:
            self.value = value
            self.condition.notify()
    def close(self):
        self.put(self.sentinel)
(因为我现在使用
None
来表示什么都没有,所以我必须创建一个单独的哨兵来表示我们已经完成了。)

这种设计的问题在于,如果生产者在消费者忙于处理的情况下输入多个值,它可能会错过其中的一些值,但在这种情况下,这个“问题”正是您所寻找的


尽管如此,使用低级工具总是意味着出错的机会更多,这对于线程同步来说尤其危险,因为它涉及的问题很难让人理解,甚至在理解它们的情况下也很难调试,所以你最好还是使用
队列

那是什么
fsevents
?据我所知,在该名称下唯一的库是一个在OSX10.5下停止可靠工作的库。还有PyObjC绑定和至少两个其他独立的包装器(加上各种跨平台的东西),但我不认为它们中的任何一个被称为只是
fsevents
。此外,“我先尝试过使用watchdog,但因为它必须在mac上运行”……如果你是说,上次我看到它在mac上运行得很好的话(使用
select.kqueue
、原生
kqueue
、PyObjC FSEvents或其他第三方包装程序之一,具体取决于您安装的内容)。您遇到了什么问题?您使用的是哪种后端?当我试图让watchdog正常工作时,我发现了以下页面:好的,您应该在问题中提到您正在使用的特定库。@Martin:好的,您明白我在这里做什么吗?您实际上可以通过使用一个带
条件的可变值来简化此过程ition
;我只使用了一个队列,因为你说你想跳过队列,所以我想你会理解这一点……我对编程非常陌生,我正在尝试了解这个概念。我刚刚测试了它,但我仍然存在一个问题,当我在文件夹中添加三个文件时,程序仍在处理第一个文件,其他所有文件都是e在第一个文件完成后执行。如何防止这种情况发生?我只希望将最新的文件添加到正在使用的文件夹中,而忘记在代码仍然有效时添加的其他文件