-3

I want to make this little application to update the information from the tkinter window every 1 second. The application shows computer info and generates a .txt file and then parses that into a tkinter window, which is the first issue with the app, which will not help if I want to update the contents of the tkinter windows every 1 second, since I also need to update the .txt file first.

I've created a class (UpdateTextTkinter) just to test if I can update text from a window by pressing a button - I was thinking about using it to update contents everytime I press the button.

What I need help or ideas with:

  1. How to migrate from .txt to tkinter window to only generating a tkinter window and appending text to it?
  2. How to update the window every 1 second with new information?

Here's the code:

# check if file exists, if not create with WRITE flag
path_text = pathlib.Path("path") # path to txt file
if path_text.is_file():
    # make file WRITABLE
    filename = "path" # path to txt file
    os.chmod(filename, S_IWUSR)
else:
    # pop-up: file not found and will be created
    response = win32ui.MessageBox("File inexistent - will be created", "Exception: File not found", win32con.MB_OKCANCEL)
    if response == win32con.IDCANCEL:
        # branch to exit execution if CANCEL is pressed
        exit()
    # branch to continue execution if OK is pressed
    elif response == win32con.IDOK:
        # file was not found, create it here and apprend it with data (write flag)
        f = open("path", "w+") #path to txt file
# covert large numbers of bytes into a defined format (kilo, mega, giga, tera, peta)
def get_size(bytes, suffix="B"):
    """
    Scale bytes to proper format:

    1253656 -> '1.20MB'
    1253656678 -> '1.17GB'
    :param bytes:
    :param suffix:
    :return:
    """
    factor = 1024
    for unit in ["", "K", "M", "G","T", "P"]:
        if bytes < factor:
            return f"{bytes:.2f}{unit}{suffix}"
        bytes /= factor


# class UpdateTextTkinter:
#     def __init__(self):
#         self.root = tk.Tk()
#         self.text = tk.StringVar()
#         # pass object to be updated
#         self.text.set("Test")
#         self.label = tk.Label(self.root, textvariable=self.text)
#
#         self.button = tk.Button(self.root,
#                                 text = "UPDATE",
#                                 command = self.changeText)
#         self.button.pack()
#         self.label.pack()
#         self.root.mainloop()
#
#     # define changeText function and pass object to be updated
#
#     def changeText(self):
#         self.text.set("Test u")
#
#
# app = UpdateTextTkinter()

# Reminder
print("="*40, "REMINDER", "="*40, file = f)
now_time = datetime.now()
current_time = now_time.strftime("%H:%M:%S")
print(f"Keep in mind that this is not updating live, it's just a snapshot of the system at a certain time({current_time})!", file = f)


# Sys info
print("\n", "="*40, "System Information", "="*40, file = f)
uname = platform.uname()
print(f"System: {uname.system}", file = f)
print(f"Node Name: {uname.node}", file = f)
print(f"Release: {uname.release}", file = f)
print(f"Version: {uname.version}", file = f)
print(f"Machine: {uname.machine}", file = f)
print(f"Processor: {uname.processor}", file = f)


# Get boot date and time
print("\n", "="*40, "BOOT Time", "="*40, file = f)
boot_time_timestamp = psutil.boot_time()
bt = datetime.fromtimestamp(boot_time_timestamp)
print(f"Boot date: {bt.day}/{bt.month}/{bt.year}", file = f)
print(f"Boot time: {bt.hour}/{bt.minute}/{bt.second}", file = f)


# CPU info
print("\n", "="*40, "CPU Info", "="*40, file = f)

# Get number of Cores
print("Physical cores: ",psutil.cpu_count(logical=False), file = f)
print("Threads: ",psutil.cpu_count(logical=True), file = f)

# CPU frequencies
cpufrequency = psutil.cpu_freq()
print(f"Mininum frequency: {cpufrequency.min:.2f}MHz", file = f)
print(f"Maximum frequency: {cpufrequency.max:.2f}MHz", file = f)
print(f"Current frequency: {cpufrequency.current:.2f}MHz", file = f)

# CPU usage
print("CPU Usage Per Core:", file = f)
for i, percentage in enumerate(psutil.cpu_percent(percpu = True, interval = 1)):
    print(f"Core {i}: {percentage}%", file = f)
print(f"Total CPU Usage: {psutil.cpu_percent()}%", file = f)


# MEM information
print("\n", "="*40, "Memory Information", "="*40, file = f)

# get memory details
svmem = psutil.virtual_memory()
print(f"Total memory: {get_size(svmem.total)}", file = f)
print(f"Available memory: {get_size(svmem.available)}", file = f)
print(f"Used memory: {get_size(svmem.used)}", file = f)
print(f"Percentage memory: {svmem.percent}%", file = f)

# get swap memory (if existent)
swap = psutil.swap_memory()
print(f"Total swap memory: {get_size(swap.total)}", file = f)
print(f"Free swap memory: {get_size(swap.free)}", file = f)
print(f"Used swap memory: {get_size(swap.used)}", file = f)
print(f"Percentage swap memory: {swap.percent}%", file = f)


# DISK usage
print("\n", "="*40, "Disk Information", "="*40, file = f)
print("Partitions and usage:", file = f)

# get all disk partitions
partitions = psutil.disk_partitions()
for partitions in partitions:
    print(f"\nDevice: {partitions.device}", file = f)
    print(f"Mountpoint: {partitions.mountpoint}", file = f)
    print(f"File sys type: {partitions.fstype}", file = f)
    try:
        partitions_usage = psutil.disk_usage(partitions.mountpoint)
    except PermissionError:
        # can't be catched due to disk that isn't ready
        continue
    print(f"Total size: {get_size(partitions_usage.total)}", file = f)
    print(f"Used space: {get_size(partitions_usage.used)}", file = f)
    print(f"Free space: {get_size(partitions_usage.free)}", file = f)
    print(f"Percentage size: {partitions_usage.percent}%", file = f)

# get IO statistics since boot
disk_io = psutil.disk_io_counters()
print(f"Total read: {get_size(disk_io.read_bytes)}", file = f)
print(f"Total write: {get_size(disk_io.write_bytes)}", file = f)


# Network information
print("\n", "="*40, "Network Information", "="*40, file = f)
# get all network interfaces (virtual and physical)
if_addrs = psutil.net_if_addrs()
for interface_name, interface_addresses in if_addrs.items():
    for address in interface_addresses:
        print(f"=== Interface: {interface_name} ===", file = f)
        if str(address.family) == 'AddressFamily.AF_INET':
            print(f"  IP Address: {address.address}", file = f)
            print(f"  Netmask: {address.netmask}", file = f)
            print(f"  Broadcast IP: {address.broadcast}", file = f)
        elif str(address.family) == 'AddressFamily.AF_PACKET':
            print(f"  MAC Address: {address.address}", file = f)
            print(f"  Netmask: {address.netmask}", file = f)
            print(f"  Broadcast MAC: {address.broadcast}", file = f)
# get IO statistics since boot
net_io = psutil.net_io_counters()
print(f"Total Bytes Sent: {get_size(net_io.bytes_sent)}", file = f)
print(f"Total Bytes Received: {get_size(net_io.bytes_recv)}", file = f)


# Make file READ-ONLY
# filename = "path" #path to txt file
# os.chmod(filename, S_IREAD)

#Close file
f.close()

# Import text file and parse it into a tkinter GUI
# filepath = "path" #path to txt file

root = Tk()
root.title("Computer Informations")
root.iconbitmap("C:\\Users\\User\\PycharmProjects\\FirstSteps\\Computer_info\\iconbitmap")
# open file as in Tkinter (read-only)
with open("path", "r") as f: # path to txt file
    # display file in a tkinter window
    Label(root, text=f.read()).pack()

root.mainloop()

# Delete file after is parsed in Tkinter
if os.path.exists("path"): # path to txt file
    os.remove("path") # path to txt file
else:
    # create message box error: file not found, cannot be deleted
    exit_response = win32ui.MessageBox("File inexistent - program will exit", "Exception: File not found", win32con.MB_OK)
    # branch to continue exectuion if OK is pressed
    if exit_response == win32con.IDOK:
        exit()

PS: The code to display sys-info is from the internet, I'm trying to learn more Python by using it!

THANK YOU!

Mihail
  • 9
  • 2
  • 9
  • 1
    For the code that needs to run every second, how long does that code take to run? Is it less than a couple hundred milliseconds? Less than a second? More than a second? The answer will determine the proper method to use. – Bryan Oakley Jun 12 '20 at 13:15
  • 1
    Does this answer your question? [making-python-tkinter-label-widget-update](https://stackoverflow.com/questions/1918005) – stovfl Jun 12 '20 at 13:35
  • 1
    @BryanOakley without input from the user the code will run in less than one second. I don't see you're reference to threads and timers, probably deleted it, but yes, I've started looking into threads to learn how I can make use of them. – Mihail Jun 15 '20 at 10:43
  • 1
    @stovfl I'm looking into it, also started reading "Tkinter Label Widget" – Mihail Jun 15 '20 at 10:47
  • 1
    @BryanOakley since 'root.mainloop()' is used as an infinite loop to keep the tkinter window on the screen and to update contents of that window, can I update only the .txt file it's generating and do something in order to update the window with 'mainloop()' or its not possible? – Mihail Jun 15 '20 at 11:40

1 Answers1

1

For updating the window every period of time, you can use threads as follows:

from threading import Thread
from time import sleep

def update():
    while True:
        # do what you want to update here
        sleep(1)

# and to start the thread, just do
Thread(target=update).start()
Amin Guermazi
  • 1,632
  • 9
  • 19