我正在为一项任务创建一个客户端/服务器程序,目标是将客户端程序的输入发送到服务器程序,然后服务器程序获取所述输入并使用它来询问 OHM(开放硬件监视器)以获取总体 CPU 温度、CPU 负载、每个 CPU 核心温度,然后将这些发送回客户端,客户端将它们写入 JSON 文件,然后使用该文件获取所需的数据并将其显示在 tkinter GUI 上。
我的程序的每个部分都按预期工作,除了我似乎无法从 JSON 文件中提取信息,而且我看不出哪里出了问题。
服务器程序:
import queue
import socket
import threading
import time
import wmi
import json
import pythoncom
queue_1 = queue.Queue(maxsize=50) # queue for user instructions
queue_2 = queue.Queue(maxsize=1) # queue for received data --> write to json
class ReceiveData(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
print("ReceiveData thread initialised")
# define port and IP for receiving data
UDP_IP = "127.0.0.1"
UDP_PORT = 9994
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.sock.settimeout(60)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.sock.bind((UDP_IP, UDP_PORT))
def run(self):
while True:
if not queue_1.full():
try:
data, addr = self.sock.recvfrom(4096) # buffer is 1024 bytes
# print(f"received {data}")
data = data.decode("utf-8")
queue_1.put(data)
# print("received data put in queue")
except socket.timeout:
print("didn't receive any data (ReceiveData)")
self.sock.close()
class HardwareMonitor(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
print("HWM Thread initialised")
self.hwmon = None
self.sensors = None
self.instruction = None
self.cpu_temps = None
self.sens_name = None
self.current_time = None
self.sens_type = None
self.cpu_load = None
def run(self):
while True:
try:
self.instruction = queue_1.get()
print("took information off of queue1")
# sensor: "CPU Package"
# value: "Temperature"
pythoncom.CoInitialize()
self.hwmon = wmi.WMI(namespace=r"root\OpenHardwareMonitor")
self.sensors = self.hwmon.Sensor()
for sensor in self.sensors:
if sensor.SensorType == u'Temperature' and sensor.Name == "CPU Package":
self.cpu_temps = sensor.value
self.sens_name = sensor.Name
self.sens_type = sensor.SensorType
self.current_time = time.strftime("%H:%M:%S", time.localtime())
# print(f"CPU is {self.cpu_temps}°C on {self.sens_name} the time of read {self.current_time}")
if sensor.SensorType == u'Load' and sensor.Name == "CPU Total":
self.cpu_load = sensor.value
self.sens_name = sensor.Name
self.sens_type = sensor.SensorType
self.current_time = time.strftime("%H:%M:%S", time.localtime())
# print(f"CPU load is {self.cpu_load}% on {self.sens_name} time of read {self.current_time}")
load_dict = {
"Name": self.sens_name,
"Sensor Type": self.sens_type,
"Value": self.cpu_temps
}
json_str = json.dumps(load_dict)
print(json_str)
queue_2.put(json_str)
print("data put in queue2")
except:
pass
class SendData(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
print("SendData thread initialised")
self.send = True
self.UDP_IP = "127.0.0.1"
self.UDP_PORT = 9997
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.run()
# print("Getting here")
def run(self):
time.sleep(2)
while True:
if not queue_2.empty():
q_data = queue_2.get()
# print(type(q_data))
print("got information from queue2")
s_data = json.dumps(q_data)
# print("I just got to here")
print(f"sending data - {s_data}")
self.sock.sendto(bytes(str(s_data), "utf-8"), (self.UDP_IP, self.UDP_PORT))
time.sleep(1)
elif queue_2.empty():
print("queue2 was empty")
break
def main():
receiver = ReceiveData()
receiver.start()
hardware = HardwareMonitor()
hardware.start()
sender = SendData()
sender.start()
if __name__ == '__main__':
main()
客户端程序
import queue
import socket
import threading
import json
import time
from tkinter import *
from tkinter import filedialog
import tkinter as tk
queue_1 = queue.Queue(maxsize=1) # queue for user instructions
queue_2 = queue.Queue(maxsize=50) # queue for received data --> write to json
class JSONWriter:
def __init__(self, signal):
self.signal = signal
print("JSON Writer started")
# self.num_records = num_records
# self.time_spacing = time_spacing
def write(self, record):
with open(self.signal, 'a') as outfile:
json_data = json.dumps(record) + '\n'
parsed = json.loads(json_data)
json.dump(parsed, outfile, indent=4, sort_keys=True)
print(json.dumps(parsed, indent=4, sort_keys=True))
class SendInstructions(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
print("Sender thread started")
self.UDP_IP = "127.0.0.1"
self.UDP_PORT = 9994
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.sock.settimeout(20)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
def run(self):
try:
while True:
data = queue_1.get()
# print(data)
data = json.dumps(data)
self.sock.sendto(bytes(str(data), "utf-8"), (self.UDP_IP, self.UDP_PORT))
# print("request sent to server")
except socket.timeout:
print("didn't receive any data (ReceiveData)")
self.sock.close()
print("receive socket closed")
class ReceiveData(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
print("receiving started")
# print("Receiver thread started")
# define port and IP for receiving data
UDP_IP = "127.0.0.1"
UDP_PORT = 9997
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.sock.bind((UDP_IP, UDP_PORT))
def run(self):
while True:
data, addr = self.sock.recvfrom(4096) # buffer is 1024 bytes
data = data.decode("utf-8")
print(f"received {data}")
queue_2.put(data)
class Export(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
print("Export thread started")
def run(self):
while True:
try:
print("Export loop started")
data = queue_2.get()
with open("Export.json", 'a') as temps:
temps_str = json.dumps(data,
indent=4, sort_keys=True,
ensure_ascii=False)
print(f"exporting {temps_str}")
temps.write(temps_str)
temps.write("\n")
except QueueEmptyError:
print("Queue 2 was empty")
pass
class ClientGUI(threading.Thread):
def __init__(self, master):
threading.Thread.__init__(self)
print("tkinter thread booted")
master.title("Client GUI")
master.geometry('600x600')
self.txt_cpu = Text(master, height=2, width=51)
self.txt_cpu.pack(padx=10, pady=10)
self.txt_cpu.delete("1.0", END)
self.txt_cpu.after(1000, self.update_text())
self.close_button = Button(master, text="Close", command=master.quit)
self.close_button.pack()
def update_text(self):
print("update text running")
try:
dictionary = self.load_dict()
# print(dictionary)
self.txt_cpu.delete("1.0", tk.END)
self.txt_cpu.after(1000, self.update_text())
except FileNotFoundError:
print("Export.txt not found.")
self.txt_cpu.after(1000, self.update_text())
def load_dict(self):
with open('Export.json', 'r') as f:
lines = f.read().splitlines()
last_line = lines[-1]
print(last_line)
def run(self):
print("Record print started")
num_records = 100
timespacing_seconds = 1
current_time = time.strftime('%Y%m%d_%H%M%S')
filename_json = current_time + "_" + str(timespacing_seconds) + ".json"
control_writer = JSONWriter(filename_json)
for i in range(1, num_records):
raw_data = i
control_writer.write(raw_data)
time.sleep(timespacing_seconds)
queue_1.put(raw_data)
if __name__ == '__main__':
sender = SendInstructions()
receiver = ReceiveData()
export = Export()
sender.start()
receiver.start()
export.start()
root = Tk()
client_gui = ClientGUI(root)
client_gui.start()
root.mainloop()
Export.json 文件示例
"\"{\\\"Name\\\": \\\"CPU Total\\\", \\\"Sensor Type\\\": \\\"Load\\\", \\\"Value\\\": 38.875}\""
"\"{\\\"Name\\\": \\\"CPU Total\\\", \\\"Sensor Type\\\": \\\"Load\\\", \\\"Value\\\": 39.5}\""
"\"{\\\"Name\\\": \\\"CPU Total\\\", \\\"Sensor Type\\\": \\\"Load\\\", \\\"Value\\\": 39.75}\""
"\"{\\\"Name\\\": \\\"CPU Total\\\", \\\"Sensor Type\\\": \\\"Load\\\", \\\"Value\\\": 39.75}\""
"\"{\\\"Name\\\": \\\"CPU Total\\\", \\\"Sensor Type\\\": \\\"Load\\\", \\\"Value\\\": 39.625}\""
"\"{\\\"Name\\\": \\\"CPU Total\\\", \\\"Sensor Type\\\": \\\"Load\\\", \\\"Value\\\": 40.0}\""
"\"{\\\"Name\\\": \\\"CPU Total\\\", \\\"Sensor Type\\\": \\\"Load\\\", \\\"Value\\\": 40.0}\""
"\"{\\\"Name\\\": \\\"CPU Total\\\", \\\"Sensor Type\\\": \\\"Load\\\", \\\"Value\\\": 40.0}\""
"\"{\\\"Name\\\": \\\"CPU Total\\\", \\\"Sensor Type\\\": \\\"Load\\\", \\\"Value\\\": 39.75}\""
"\"{\\\"Name\\\": \\\"CPU Total\\\", \\\"Sensor Type\\\": \\\"Load\\\", \\\"Value\\\": 39.875}\""
"\"{\\\"Name\\\": \\\"CPU Total\\\", \\\"Sensor Type\\\": \\\"Load\\\", \\\"Value\\\": 39.625}\""
"\"{\\\"Name\\\": \\\"CPU Total\\\", \\\"Sensor Type\\\": \\\"Load\\\", \\\"Value\\\": 39.75}\""
我尝试了很多不同的事情,尝试改变我发送字典的方式等,但似乎没有任何效果。
我无法测试它,但我认为我看到了问题 - 你使用
dumps()
两次,这给出了奇怪的字符串。
服务器将数据放入
dumps()
时运行 queue
然后当客户端从 queue
获取数据时,它会再次运行 dumps()
但它应该使用 loads()
将字符串转换回字典(稍后使用 dumps()
发送它)
或者它应该发送从队列中获取的字符串而不使用 dumps
while True:
data = queue_1.get()
# print(data)
data = json.dumps(data) # <--- remove it
self.sock.sendto(bytes(str(data), "utf-8"), (self.UDP_IP, self.UDP_PORT))
# print("request sent to server")