如何从 JSON 文件中提取数据以在 tkinter GUI 上显示

问题描述 投票:0回答:1

我正在为一项任务创建一个客户端/服务器程序,目标是将客户端程序的输入发送到服务器程序,然后服务器程序获取所述输入并使用它来询问 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}\""

我尝试了很多不同的事情,尝试改变我发送字典的方式等,但似乎没有任何效果。

python json oop tkinter openhardwaremonitor
1个回答
0
投票

我无法测试它,但我认为我看到了问题 - 你使用

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")
© www.soinside.com 2019 - 2024. All rights reserved.