如何在检测到文件更改时发送消息?扭曲和Web套接字
问题描述:
我目前正在尝试创建一个小型演示,其中我的电脑和我的本地主机之间连接了一个Web套接字ws://localhost:8080/ws
。我想让网络套接字监视计算机上的文件以进行更改。如果有变化,请发送消息。使用Advanced Rest Client监视连接和输出。如何在检测到文件更改时发送消息?扭曲和Web套接字
有没有一种特定的方法可以用于课堂上不断检查这个文件的内容?
编辑
我已经实现了使用watchdog
检测的指定目录中的文件的任何事件的观察员。但是,我的消息不是在sendFSEvent
方法中发送的,我也意识到当我连接到Web套接字时,我的客户端未被注册。
这里是我的代码在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("\nSent 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("\nGoodbye")
sys.exit(1)
任何帮助将不胜感激。
谢谢
布赖恩
答
大多数企业发行版都配备inotify
这实在是非常适合监控文件和目录。基本思想是在连接时捕获连接的Web套接字客户端列表。然后创建一个回调,当您正在监视的文件发生更改时执行回调。在此回调中,您可以迭代客户端并向他们发送消息,如'file: "blah/blah.txt" has changed'
。这有点过分,但代码片段应该为你清理一些东西。
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 ...
您将在哪个操作系统上运行此应用程序? –
Windows现在,但将切换到Linux(红帽)。 – Brian
在* nix中,有一个文件的'mtime'属性(参见'os.path.getmtime(path)'),您可以定期检查它。另一种选择是计算文件的校验和,并在更改时采取行动。 – boardrider