Python Forum
Updating/running code when path changes
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Updating/running code when path changes
#1
Hello

I’m working on a project and I need help.

I have a Raspberry Pi that is connected to a small display. I want the display to show the current moon phase, I’ve already downloaded all the images, labeled 000.png to 360.png. The numbers stand for the relative phase angle of the current moon.

I’ve managed to create a script that scrapes the phase angle from a website and puts it in a json file.

Something like this:

[{"text": 270}]

So what needs to happen next is I need to update the image currently being shown, in this case I would be showing in my python script image /269.png but I want that filename to update to the latest number from the json file, so in this case update to /270.png

I have this code that creates the path: (I’m new in python and generally not good with coding)

path = "near_side_1024x1024x8/"

with open('number.json', 'r') as f:
    distros_dict = json.load(f)

for distro in distros_dict:

    op = json.dumps(distro["text"])

str = path+op+".png"

print(str)
This results in: near_side_1024x1024x8/270.png

But now I’m stuck, I’ve tried tkinter and pygame, and I’ve managed to get the image to display fullscreen but what I have not accomplished is to have the image update when new phase angle value has been fetched, what do I need to do in python to run the code again to update the image after lets say 10 min? Or when a change in the json file is detected? Is there some loop function?

At the moment the only way for me to update the image is by closing the python script and running it again.

I hope I’ve explained this well enough. I’m very new in python and programming in general.
Reply
#2
You need a periodic event. In tkinter you could use .after() to call a function.
def update_phase():
    with open('number.json', 'r') as f:
        distros_dict = json.load(f)
    for distro in distros_dict:
        op = json.dumps(distro["text"])
    str = path+op+".png"
    # Open file and update image

    # Repeat in an hour 3,600,000 milliseconds
    root.after(3600000, update_phase)
Reply
#3
(Jul-06-2022, 01:12 PM)deanhystad Wrote: You need a periodic event. In tkinter you could use .after() to call a function.
def update_phase():
    with open('number.json', 'r') as f:
        distros_dict = json.load(f)
    for distro in distros_dict:
        op = json.dumps(distro["text"])
    str = path+op+".png"
    # Open file and update image

    # Repeat in an hour 3,600,000 milliseconds
    root.after(3600000, update_phase)

Thanks. But I now get this error:
Error:
AttributeError: type object 'str' has no attribute 'read'
I'm trying to figure out what it means.
Reply
#4
Please post code and the entire error message, including trace.
Reply
#5
line 6 str is a python built in. You are re-assigning it. Maybe something like my_string = str(my_path) Not sure if that is the problem but, maybe one of the more experienced can help better.
I welcome all feedback.
The only dumb question, is one that doesn't get asked.
My Github
How to post code using bbtags


Reply
#6
That is bad programming making a built-in function unavailable, but it is not the reason for the error. Somewhere, in code we haven't been shown, somebody is trying to use a filename as though it were a file object (my best guess).
Reply
#7
Here's the full code and error:

import json
import os
import tkinter
import PIL
import PIL.Image

import tkinter as tk
from PIL import Image, ImageTk
import numpy as np

path = "near_side_1024x1024x8/"

def update_phase():
    with open('number.json', 'r') as f:
        distros_dict = json.load(f)
    for distro in distros_dict:
        op = json.dumps(distro["text"])
    str = path+op+".png"
    # Open file and update image

    # Repeat in an hour 3,600,000 milliseconds
    root.after(3600000, update_phase)

import sys
if sys.version_info[0] == 2:  # the tkinter library changed it's name from Python 2 to 3.
    import Tkinter
    tkinter = Tkinter #I decided to use a library reference to avoid potential naming conflicts with people's programs.
else:
    import tkinter
from PIL import Image, ImageTk

def showPIL(pilImage):
    root = tkinter.Tk()
    w, h = root.winfo_screenwidth(), root.winfo_screenheight()
    root.overrideredirect(1)
    root.geometry("%dx%d+0+0" % (w, h))
    root.focus_set()
    root.bind("<Escape>", lambda e: (e.widget.withdraw(), e.widget.quit()))
    canvas = tkinter.Canvas(root,width=w,height=h)
    canvas.pack()
    canvas.configure(background='black')
    imgWidth, imgHeight = pilImage.size
    if imgWidth > w or imgHeight > h:
        ratio = min(w/imgWidth, h/imgHeight)
        imgWidth = int(imgWidth*ratio)
        imgHeight = int(imgHeight*ratio)
        pilImage = pilImage.resize((imgWidth,imgHeight), Image.ANTIALIAS)
    image = ImageTk.PhotoImage(pilImage)
    imagesprite = canvas.create_image(w/2,h/2,image=image)
    root.mainloop()

pilImage = Image.open(str)
showPIL(pilImage)
Error:
^CHermanns-MacBook-Pro:test hermann$ python3 tkinter1.py Traceback (most recent call last): File "/Users/hermann/.pyenv/versions/3.9.0/lib/python3.9/site-packages/PIL/Image.py", line 3072, in open fp.seek(0) AttributeError: type object 'str' has no attribute 'seek' During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/Users/hermann/Dropbox/electronics/moon/test/tkinter1.py", line 52, in <module> pilImage = Image.open(str) File "/Users/hermann/.pyenv/versions/3.9.0/lib/python3.9/site-packages/PIL/Image.py", line 3074, in open fp = io.BytesIO(fp.read()) AttributeError: type object 'str' has no attribute 'read'
Reply
#8
Sorry Menator, you were right.

The str() function is being used as a str object in line 52. Previously the program "corrected" this by reassigning the "str" variable to reference a string instead of a function.
str = path+op+".png"  # This changes str from referencing a function to a string
The code is all wrong for a display that will update over time. It should create the tkinter window first, then call a periodic function to get the moon phase and load the proper image.
import json
import tkinter
import tkinter as tk
from PIL import Image, ImageTk
import numpy as np

path = "near_side_1024x1024x8/"

def update_phase():
    """Retrieve moon phase and update image"""
    with open("number.json", "r") as f:
        distros_dict = json.load(f)
    for distro in distros_dict:
        op = json.dumps(distro["text"])
    # Open file and update image
    showPIL(path + op + ".png")

    # Run myself again after an hour (3,600,000 milliseconds)
    root.after(3600000, update_phase)

def showPIL(filename):
    """Open image file and draw image on canvas"""
    pilImage = Image.open(filename)
    imgWidth, imgHeight = pilImage.size
    if imgWidth > w or imgHeight > h:
        ratio = min(w / imgWidth, h / imgHeight)
        imgWidth = int(imgWidth * ratio)
        imgHeight = int(imgHeight * ratio)
        pilImage = pilImage.resize((imgWidth, imgHeight), Image.ANTIALIAS)
    image = ImageTk.PhotoImage(pilImage)
    imagesprite = canvas.create_image(w / 2, h / 2, image=image)

root = tkinter.Tk()
w, h = root.winfo_screenwidth(), root.winfo_screenheight()
root.overrideredirect(1)
root.geometry("%dx%d+0+0" % (w, h))
root.focus_set()
root.bind("<Escape>", lambda e: (e.widget.withdraw(), e.widget.quit()))
canvas = tkinter.Canvas(root, width=w, height=h)
canvas.pack()
canvas.configure(background="black")

update_phase()  # Starts the update loop
root.mainloop()
Reply
#9
Thank you deanhystad, but now all I get is black background and no image. Thank you for your help!
Reply
#10
The most likely error is it failed to open an image to display. I didn't test any of my code, and I could have introduced an error when I modified your source.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  running the code and seeing the GUI chriswrcg 1 800 May-19-2023, 04:49 PM
Last Post: deanhystad
  [PyQt] source code is not running in REDHAT 7 linux platform shridhara 0 2,115 May-23-2018, 07:58 AM
Last Post: shridhara
  Errors while running dash plotly code Nischitha 3 5,234 Aug-24-2017, 10:54 AM
Last Post: Larz60+

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020