python - Sådan sender du besked, når filændringer opdages? Twisted og Web Sockets

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg forsøger for øjeblikket at oprette en lille demo, hvor jeg forbinder en stikkontakt mellem min computer og mit lokalehost ws://localhost:8080/ws. Jeg vil have webstikket til at overvåge en fil på min computer til ændringer. Hvis der er ændringer, send en besked. Tilslutningen og udgangen overvåges ved hjælp af Advanced Rest Client.


Er der en bestemt metode, jeg kan bruge på klassen til konstant at kontrollere indholdet af denne fil?


EDIT



Jeg har implementeret en observatør ved hjælp af watchdog, der registrerer enhver begivenhed for filer i en bestemt mappe. Men min besked sendes ikke i sendFSEvent metoden, og jeg indså også, at min klient ikke er registreret, når jeg opretter forbindelse til webstikket.


Her er min kode i server.py


import sys
import os

from watchdog.observers import Observer
from twisted.web.static import File
from twisted.python import log
from twisted.web.server import Site
from twisted.internet import reactor, defer

from autobahn.twisted.websocket import WebSocketServerFactory, 
    WebSocketServerProtocol, listenWS

from MessangerEventHandler import MessangerEventHandler


class WsProtocol(WebSocketServerProtocol):
    def connectionMade(self):
        print("Connection made")
        WebSocketServerProtocol.connectionMade(self)

    def onOpen(self):
        WebSocketServerProtocol.onOpen(self)
        print("WebSocket connection open")

    def onMessage(self, payload, isBinary):
        print("Message was: {}".format(payload))
        self.sendMessage("message received")

    def sendFSEvent(self, json):
        WebSocketProtocol.sendMessage(self, json)
        print('Sent FS event')

    def onClose(self, wasClean, code, reason):
        print("Connection closed: {}".format(reason))
        WebSocketServerProtocol.onClose(self, wasClean, code, reason)


class WsServerFactory(WebSocketServerFactory):
    protocol = WsProtocol

    def \_\_init\_\_(self, url='ws://localhost', port=8080):
        addr = url + ':' + str(port)
        print("Listening on: {}".format(addr))
        WebSocketServerFactory.\_\_init\_\_(self, addr)
        self.clients = []

    def register(self, client):
        if not client in self.clients:
            print("Registered client: {}".format(client))
            self.clients.append(client)

    def unregister(self, client):
        if client in self.clients:
            print("Unregistered client: {}".format(client))
            self.clients.remove(client)
        self.\_printConnected()

    def \_printConnected(self):
        print("Connected clients:[")

    def notify\_clients(self, message):
        print("Broadcasting: {}".format(message))
        for c in self.clients:
            c.sendFSEvent(message)
        print("
Sent messages")


if \_\_name\_\_ == '\_\_main\_\_':
    if len(sys.argv) < 2:
        print("Usage: python server\_defer.py <dirs>")
        sys.exit(1)

    log.startLogging(sys.stdout)

    ffactory = WsServerFactory("ws://localhost", 8080)
    ffactory.protocol = WsProtocol
    listenWS(ffactory)

    observers = []
    for arg in sys.argv[1:]:
        dir\_path = os.path.abspath(arg)
        if not os.path.exists(dir\_path):
            print('{} does not exist.'.format(dir\_path))
            sys.exit(1)
        if not os.path.isdir(dir\_path):
            print('{} is not a directory.'.format(dir\_path))
            sys.exit(1)

        # Check for and handle events
        event\_handler = MessangerEventHandler(ffactory, reactor, os.getcwd())

        observer = Observer()
        observer.schedule(event\_handler, path=dir\_path, recursive=True)
        observer.start()

        observers.append(observer)

    try:
        reactor.run()
    except KeyboardInterrupt:
        for obs in observers:
            obs.stop()
        reactor.stop()
        print("
Goodbye")
        sys.exit(1)


Enhver hjælp ville blive meget værdsat.


Tak skal du have,


Brian

Bedste reference


De fleste virksomhedsdistroer kommer med inotify, som er rigtig velegnet til overvågning af filer og mapper. Den grundlæggende idé er at indfange en liste over tilsluttede web-sokkelklienter, da de forbinder. Derefter oprette en tilbagekaldelse, der vil udføres, når der sker en ændring på de filer, du overvåger. Inden for denne tilbagekaldelse kan du gentage klienterne og sende dem en besked som 'file: "blah/blah.txt" has changed'. Det er lidt wonky, men kodestykket bør rydde op for dig.


from functools import partial
from twisted.internet import inotify
from twisted.python import filepath
# the rest of your imports ...


class SomeServerProtocol(WebSocketServerProtocol):
    def onConnect(self, request):
        self.factory.append(self)       # <== append this client to the list in the factory


def notification\_callback(ignored, filepath, mask, ws\_clients):
    """
    function that will execute when files are modified
    """
    payload = "event on {0}".format(filepath)
    for client in ws\_clients:
        client.sendMessage(
            payload.encode('utf8'),    # <== don't forget to encode the str to bytes before sending!
            isBinary = False)

if \_\_name\_\_ == '\_\_main\_\_':
    root = File(".")
    factory = WebSocketServerFactory(u"ws://127.0.01:8080")
    factory.protocol = SomeServerProtocol
    factory.clients = []        # <== create a container for the clients that connect

    # inotify stuff
    notify = partial(notification\_callback, ws\_clients=factory.clients)   # <== use functools.partial to pass extra params
    notifier = inotify.INotify()
    notifier.startReading()
    notifier.watch(filepath.FilePath("/some/directory"), callbacks=[notify])

    # the rest of your code ...