首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >watchdog.observers.Observer在Windows中工作,在Linux上工作在docker中,在Windows上不工作

watchdog.observers.Observer在Windows中工作,在Linux上工作在docker中,在Windows上不工作
EN

Stack Overflow用户
提问于 2021-04-01 17:45:14
回答 2查看 1.3K关注 0票数 5

我有一个有趣的问题要把我逼疯。我有一个使用watchdog.observers.Observer的python程序。此程序(又名观察者)监视文件夹,并在文件出现时作出响应。我有另一个程序(也就是解析器),它定期地用文件填充被监视的文件夹。

  1. 当监视程序在Windows中运行,解析器在Windows上的停靠容器中运行时,就会感到幸福。
  2. 当观察者程序在Linux盒上的坞容器中运行,而解析器在Linux盒上的另一个坞容器中运行时,就会有快乐。
  3. 当观察者程序在Windows上的坞容器中运行,而解析器在Windows上的另一个坞容器中运行时,幸福是无法实现的。解析器用文件填充文件夹,但观察者从不观察它们。

这是我的观察代码:

代码语言:javascript
复制
import os
import sys
import time
   
from watchdog.observers import Observer
from event_handler import ImagesEventHandler
from constants import ROOT_FOLDER, IMAGES_FOLDER, CWD


class ImagesWatcher:
    def __init__(self, src_path):
        self.__src_path = src_path
        print(self.__src_path)
        self.__event_handler = ImagesEventHandler()
        self.__event_observer = Observer()
        print("********** Inside ImagesWatcher --init__ method just after instantiating ImagesEventHandler and Observer **************")

    def run(self):
        print("********** Inside ImagesWatcher run method **************")
        self.start()
        try:
            while True:
                time.sleep(1)
        except KeyboardInterrupt:
            self.stop()

    def start(self):
        print("********** Inside ImagesWatcher start method **************")
        self.__schedule()
        self.__event_observer.start()

    def stop(self):
        print("********** Inside ImagesWatcher stop method **************")
        self.__event_observer.stop()
        self.__event_observer.join()

    def __schedule(self):
        print("********** Inside ImagesWatcher __schedule method **************")
        print(self.__src_path)
        self.__event_observer.schedule(
            self.__event_handler,
            self.__src_path,
            recursive=True
        )

if __name__ == "__main__":
    src_path = sys.argv[1] if len(sys.argv) > 1 else CWD
    src_path = os.path.abspath(src_path)
    watch_path = os.path.join(src_path, ROOT_FOLDER)
    watch_path = os.path.join(watch_path, IMAGES_FOLDER)
    print('watch_path: ' + watch_path)

    if not os.path.exists(watch_path):
        os.makedirs(watch_path)
        print('just created: ' + watch_path)

    ImagesWatcher(watch_path).run()

下面是关联的事件处理程序代码:

代码语言:javascript
复制
import os
from PIL import Image
from watchdog.events import FileSystemEventHandler
from lambda_function import lambda_handler
from time import sleep
from os.path import dirname, abspath

class ImagesEventHandler(FileSystemEventHandler):

    def __init__(self,):
        print("********** Inside event handler __init__ method **************")
    
    def on_created(self, event):
        print("********** Inside event handler on_created method **************")
        self.process(event)

    def process(self, event):
        print("********** Inside event handler process method **************")
        sleep(2)
        image = Image.open(event.src_path)
        tracking_dir=os.path.join(dirname(dirname(abspath(event.src_path))),'Tracking')
        print("********************  tracking_dir: ' + tracking_dir + ' ********************")
        lambda_handler(image,tracking_dir)

监视程序的停止方法永远不会执行。事件处理程序的init方法被执行,但是on_created和process方法都没有被执行。

下面是我如何构建和运行码头容器:

代码语言:javascript
复制
docker build -t watcher -f docker/watcher/Dockerfile . 
docker run -d --network onprem_network -v c:\My_MR:/code/My_MR --name watcher watcher 

docker build -t parser -f docker/parser/Dockerfile . 
docker run -d --network onprem_network -v c:\My_MR:/code/My_MR --name parser parser 

我的观察者Dockerfile:

代码语言:javascript
复制
FROM python:3.7.9
ENV PYTHONUNBUFFERED 1
ENV PYTHONDONTWRITEBYTECODE 1
COPY requirements.txt /requirements.txt
RUN pip install --upgrade pip -r /requirements.txt && mkdir /code 
WORKDIR /code
COPY . /code/
RUN apt update && apt-get update && apt install tesseract-ocr -y && apt-get install ffmpeg libsm6 libxext6  -y
CMD ["python", "/code/watcher.py"]

我的解析器Dockerfile:

代码语言:javascript
复制
FROM python:3.7.9
ENV PYTHONUNBUFFERED 1
ENV PYTHONDONTWRITEBYTECODE 1
COPY requirements.txt /requirements.txt
RUN pip install --upgrade pip -r /requirements.txt && mkdir /code
WORKDIR /code
COPY . /code/
RUN apt update && apt-get update && apt-get install ffmpeg -y
CMD ["python", "/code/parser.py"]

我的requirements.txt:

代码语言:javascript
复制
Pillow == 5.4.1
gql == 3.0.0a5
matplotlib == 3.0.3
numpy == 1.16.2
opencv_python == 4.4.0.44
pandas == 0.24.2
pytesseract == 0.2.6
python_ffmpeg_video_streaming == 0.1.14
watchdog == 2.0.2
requests
tesseract

任何帮助都将不胜感激。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-04-10 01:11:22

监视狗用于监视linux文件系统事件的底层API称为inotify。Windows 2后端文档的Docker指出:

如果原始文件存储在Linux文件系统中,Linux容器只接收文件更改事件(“inotify事件”)。

您正在挂载的目录c:\My_MR驻留在Windows文件系统中,因此在监视器容器中inotify无法工作。

相反,您可以使用linux文件系统路径(例如,)从WSL 2默认发行版中的~/my_mr中运行docker。

代码语言:javascript
复制
docker run -d --network onprem_network -v ~/my_mr:/code/My_MR --name watcher watcher 
docker run -d --network onprem_network -v ~/my_mr:/code/My_MR --name parser parser 

当WSL 2发行版使用\\wsl$\网络路径运行时,可以从Windows访问该目录,即\\wsl$\<Distro name>\home\<username>\my_mr (更多信息这里)。因此,我相信docker run也可以在Windows中使用\\wsl$\路径和-v

票数 2
EN

Stack Overflow用户

发布于 2022-01-12 18:33:19

Docker Windows卷监视程序

也可以使用码头Windows卷监视器。Python脚本监视托管在Windows上的Docker容器的文件夹绑定,并通过文件更改更新这些容器。

使用pip安装(支持Python2& 3)。

代码语言:javascript
复制
pip install docker-windows-volume-watcher

监视所有容器的所有目录绑定。

代码语言:javascript
复制
docker-volume-watcher

只监视容器container_name的绑定。

代码语言:javascript
复制
docker-volume-watcher container_name

只监视container_name与宿主目录C:\some\目录的绑定。

代码语言:javascript
复制
docker-volume-watcher container_name C:\some\directory

局限性

  • 脚本不会传播到容器文件删除事件。
  • 脚本要求在容器中安装stat和chmod utils。

https://forums.docker.com/t/file-system-watch-does-not-work-with-mounted-volumes/12038/9 http://blog.subjectify.us/miscellaneous/2017/04/24/docker-for-windows-watch-bindings.html

看门狗和PollingObserver()

另一个解决方案是使用类PollingObserver。但是,如果看门狗必须用一个时间表监视多个文件和文件夹,则速度要慢得多。

代码语言:javascript
复制
import sys
import time
import logging
from watchdog.observers.polling import PollingObserver
from watchdog.events import LoggingEventHandler

if __name__ == "__main__":
    logging.basicConfig(level=logging.INFO,
                        format='%(asctime)s - %(message)s',
                        datefmt='%Y-%m-%d %H:%M:%S')
    event_handler = LoggingEventHandler()
    observer = PollingObserver()
    # Limit the number of files by setup multiple schedule
    observer.schedule(event_handler, '/folder/subfolder') # All files in a subfolder
    observer.schedule(event_handler, '/folder/file') # A file
    observer.schedule(event_handler, '/folder/file2') # A file
    # etc...
    observer.start()
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        observer.stop()
    observer.join()
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66909254

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档