簡體   English   中英

將隊列傳遞給python中的看門狗線程

[英]Pass a Queue to watchdog thread in python

我有一個從主線程實例化的Indexer類,該類的實例存儲在一個變量中,例如indexer watchdog.observers.Observer()目錄中的更改,這些更改發生在另一個線程中。 我嘗試通過我的處理程序Vigilante從主線程傳遞此indexer變量,該處理程序與主線程的其他一些變量一起傳遞給ob.schedule(Vigilante(indexer)) 由於處於不同的線程中,所以無法訪問Vigilante classindexer變量。 我知道我可以使用Queue但是我不知道如何將Queue傳遞給看門狗的線程。

這是來自主線程的代碼:

if watch:
    import watchdog.observers
    from .utils import vigilante
    class callbacks:
        def __init__(self):
            pass
        @staticmethod
        def build(filename, response):
            return _build(filename, response)
        @staticmethod
        def renderer(src, mode):
            return render(src, mode)
    handler = vigilante.Vigilante(_filter, ignore, Indexer, callbacks, Mode)
    path_to_watch = os.path.normpath(os.path.join(workspace, '..'))
    ob = watchdog.observers.Observer()
    ob.schedule(handler, path=path_to_watch, recursive=True)
    ob.start()
    import time
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        ob.stop()
        Indexer.close()
    ob.join()

Indexer class用於從實例化Indexer的代碼的另一部分寫入數據庫。

這是看門狗線程中運行的Vigilante類的代碼:

class Vigilante(PatternMatchingEventHandler):
    """Helps to watch files, directories for changes"""
    def __init__(self, pattern, ignore, indexer, callback, mode):
        pattern.append("*.yml")
        self.Callback = callback
        self.Mode = mode
        self.Indexer = indexer
        super(Vigilante, self).__init__(patterns=pattern, ignore_directories=ignore)

    def vigil(self, event):
        print(event.src_path, 'modified')
        IndexReader = self.Indexer.get_index_on(event.src_path)
        dep = IndexReader.read_index()
        print(dep.next(), 'dependency')
        feedout = self.Callback.build(
            os.path.basename(event.src_path)
            ,self.Callback.renderer(event.src_path, self.Mode.FILE_MODE)
        )

    def on_modified(self, event):
        self.vigil(event)

    def on_created(self, event):
        self.vigil(event)

我需要的是一種通過Vigilante類將那些變量從主線程傳遞到看門狗線程的方法

您可以嘗試使用Observer模式 (不需要雙關語),即讓Observer類具有一個偵聽器列表,該偵聽器列表將通知其看到的任何更改。 然后讓索引器向觀察者宣布其興趣。

在我的示例中,觀察者期望訂閱者是可接收更改的可調用對象。 然后,您可以執行以下操作:

from queue import Queue
class Observable:
    def __init__(self):
        self.listeners = []
    def subscribe(listener):
        self.listeners.append(listener)
    def onNotify(change):
        for listener in self.listeners:
            listener(change)

class Indexer(Thread):
    def __init__(self, observer):
        Thread.__init__(self)
        self.q = Queue()
        observer.subscribe(self.q.put)
    def run(self):
        while True:
            change = self.q.get()

因為標准Queue是完全線程安全的,所以可以正常工作。

我終於找到了一種方法,它不會像以前那樣過多地交叉線程,而這個想法源自@EvertW的答案。 我將一個Queue從主線程傳遞給另一個線程中的Vigilante類,因此每個修改后的文件都將放入Queue ,然后從主線程中,從隊列中修改該文件,並從Indexer數據庫中讀取, Vigilante.vigil方法需要執行的所有其他任務都移到了主線程,因為這些任務取決於修改后的文件以及從Indexer數據庫讀取的內容。

該錯誤消失了:

在線程中創建的SQLite對象只能在同一線程中使用。該對象在線程ID 9788中創建,該線程ID為4288。

這是我所做的摘要:

....
q = Queue.LifoQueue(10)
handler = vigilante.Vigilante(q, _filter, ignore)
path_to_watch = os.path.normpath(os.path.join(workspace, '..'))
ob = watchdog.observers.Observer()
ob.schedule(handler, path=path_to_watch, recursive=True)
ob.start()
import time
try:
    while True:
        if not q.empty():
            modified = q.get()
            IndexReader = Indexer.get_index_on(modified)
            deps = IndexReader.read_index()
            print(deps.next(), 'dependency')
            # TODO
        else:
            print('q is empty')
            time.sleep(1)
except KeyboardInterrupt:
    ob.stop()
    Indexer.close()
ob.join()

治安警衛班:

class Vigilante(PatternMatchingEventHandler):
    """Helps to watch files, directories for changes"""
    def __init__(self, q, pattern, ignore):
        self.q = q
        super(Vigilante, self).__init__(
            patterns=pattern, 
            ignore_patterns=ignore, 
            ignore_directories=True
        )

    def vigil(self, event):
        print(event.src_path, 'modified')
        self.q.put(event.src_path)

    def on_modified(self, event):
        self.vigil(event)

    def on_created(self, event):
        self.vigil(event)
....

PS:一個忠告:對任何遇到這種看門狗線程問題的人,我的忠告是: “不要相信看門狗的線程在修改后的文件上執行任務,只是將修改后的文件取出來並對它們進行任何處理,只是任務很簡單。”

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM