看注释
都在注释了
#import os
import time
#import threading
#from threading import RLock
import datetime
import kazoo.client as ka
#from concurrent.futures import ThreadPoolExecutor
# 创建类继承多线程 重写方法
# class MyThread(threading.Thread):
# def __init__(self,cli=None,path=None):
# super().__init__()
# self.cli=cli
# self.path=path
# # 静态方法 显示信息使用
# @staticmethod
# def log(msg):
# now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
# print(f"现在的时间是{now} 消{msg}")
# def run(self):
# ka.DataWatch(client=self.cli,path=self.path,func=self.data_changes)
# def data_changes(self, data=None, stat=None, event=None):
# if event is None:
# pass
# return
# t1 = threading.get_ident()
# print (t1)
# if data is None:
# time.sleep(5)
# print("删除")
# print("开始时间"+str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')))
# time.sleep(3)
# print("结束时间" + str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')))
#print (f"data: {data}, stat: {stat}, event: {event}")
# if not data:
# try:
# raise Exception("Invalid level!")
# except Exception as e:
# self.log("节点已经删除")
# return
#
# if event is not None:
# t1 = threading.current_thread().ident
# self.log(msg=f"id为{t1} 事件:数据变化 数据为:{data.decode('utf-8')} ")
# self.log(msg='监听到数据变化')
# self.log(msg=f"数据为:{data}")
# self.log(msg=f"版本号为:{stat.version}")
# self.log(msg=f"子节点的数量:{stat.numChildren}")
class Watcher():
def __init__(self, ip="127.0.0.1", port="2181"):
self.ip = ip
self.port = port
self.address = (self.ip + ":" + self.port)
self.zk = ka.KazooClient(hosts=self.address)
self.zk.start(timeout=5)
self.old_list = []
self.path = None
# def ceshi(self, path=None):
# s=time.time()
# time.sleep(1)
# t=threading.get_ident()
# e=time.time()
# times=e-s
# print(f"开始时{s}")
# return path
def watcher(self, path=None):
self.path = path
list = self.zk.get_children(path=path)
self.old_list = list
c=[]
for i in list:
pathd = self.path + "/" + str(i)
ka.DataWatch(client=self.zk,path=pathd,func=self.data_changes)
#直接创建监视器
# with ThreadPoolExecutor(max_workers=3) as executor:
# for i in range(10):
# future=executor.submit(self.ceshi, i)
# c.append(future)
# print(c)
#线程池测试
# for node in list:
# node_path = self.path + "/" + str(node)
# t=MyThread(cli=self.zk,path=node_path)
# t.run()
#
#********本就是创建的监听器 就算线程去监听那也会在完成放置监听器后销毁
#########未解决的点:监听的节点消失后监听器并不会消失,官网有这么一句话:Because DataWatch can watch nodes that don’t exist, it can be used alternatively as a higher-level Exists watcher that survives reconnections and session loss.
#
try:
ka.ChildrenWatch(client=self.zk, path=path, func=self.child_changes, send_event=True)
except TypeError:
print("数据异常或者模块未下载")
def data_changes(self, data, stat, event=None):
try:
if not data:
print("节点已经删除")
return
if not event:
#print("节点数据没有发生变化")
return
#print('监听到数据变化')
self.log(f"监听到数据变化, 现在数据为{data} 数据长度为{stat.dataLength} 版本号为{stat.versio} 拥有的子节点的数量为{stat.numChildre} ")
# print('数据为',data)
# print('数据长度',stat.dataLength)
# print('数据版本号:',stat.version)
# print('子节点数据版本号',stat.cversion)
# print('子节点数量',stat.numChildren)
# print('事件',event)
except Exception as e:
now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
print(f"data:{data} event{event} stat:{stat} 时间{now}")
def child_changes(self, data=None,event=None):
if event is None:
pass
# 如果,没有返回事件那么直接pass
return
# 命中直接返回不走后面
# 进行的操作
# 判断长度
if event is not None:
if len(data) > len(self.old_list):
for new_node in data:
if new_node not in self.old_list:
path = self.path + "/" + str(new_node)
self.log(f"增加了新的节点{path}")
ka.DataWatch(client=self.zk,path=path,func=self.data_changes)
#给新加的节点创建监视器
# 增加了节点
self.old_list = data
return
if len(data) < len(self.old_list):
for old_node in self.old_list:
if old_node not in data:
path = self.path + "/" + str(old_node)
self.log(f"删除了节点{path}")
# 删除了节点
self.old_list = data
return
# 命中直接返回不走后面
def log(self, msg):
now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
print(f"现在的时间是{now},{msg}")
def ls(self,path=None):
now_node_list=self.zk.get_children(path=path)
#显示节点下的文件
self.log(f"当前节点下的文件有{now_node_list}")
def add(self,path=None):
if self.zk.exists(path=path) == None:
self.zk.create(path=path,makepath=True,)
self.log(f"{path} 创建完成")
else:
self.log(f"{path} 已经存在")
#递归创建
def Changes_data(self,path=None,datas=None):
#data修改后的数据
if self.zk.exists(path=path) == None:
self.log(f"{path} 已经存在")
else:
#data,stat= cli.get(path=path)
#print ("原数据为:"+data.decode("utf-8"))
#print (stat.version)
self.zk.set_async(path=path,value=datas.encode())
data,stat= self.zk.get(path=path)
D_data=data.decode("utf-8")
version=stat.version
self.log(f"现数据为:{D_data} 现数据版本为:{version}")
#更改数据
#会触发datawatch
def views_data(self,path=None,):
if self.zk.exists(path=path) == None:
self.log(f"{path} 不存在")
else:
data,stat= self.zk.get(path=path)
D_data=data.decode("utf-8")
version=stat.version
self.log(f"原数据为:{D_data} 数据版本为:{version}")
#查看数据
if __name__ == '__main__':
Watcher(ip="192.168.10.203").watcher("/he2322")
while True:
time.sleep(3)
print("watching......")
##########记录##########
#原意:用线程去监听各个节点,节点销毁后监听器也会销毁
#可以去用线程去设置监听器,但是线程并不会一直存在而是在创建完监视器后直接到了终止态
#并无什么用处(用了10个线程并行更改了共10000次数据)回显是没有问题的
#现在代码并无进行测试(几个测试的index里拆出来的)
#总结:设置了监听,监听会一直存在(节点删除后监听也存在,再次创建户会触发数据更改(datawatch))