Tkinter TclError nach dem Update auf Fedora 43Python

Python-Programme
Anonymous
 Tkinter TclError nach dem Update auf Fedora 43

Post by Anonymous »

Vor ein paar Jahren habe ich ein TK-Skript gehackt, um auf Ereignisse von der Fregatte zu warten und den Kamera-Feed für ein paar Sekunden anzuzeigen, wenn jemand an der Tür war. Es hat ohne großen Aufwand funktioniert, bis ich auf F43 (Python 3.14) aktualisiert habe. Jetzt stecke ich fest und schaue aus dem Fenster wie einer dieser Leute, die nach draußen gehen!
Ich vermute, dass das Problem irgendwo zwischen Anfragen und Threading liegt, bin mir aber nicht sicher, wie ich das weiter beheben kann. FWIW Ich versuche nicht, die Anfrage zu threaden (hier gibt es kein aiohttp oder asyncio), sondern nur einen Thread für tk und einen Thread für mqtt (dessen Rückruf der Ort ist, an dem die Anfrage stattfindet).
Dieser Verdacht wird durch die Möglichkeit geschürt, stream() von main() aus aufzurufen, und es funktioniert wie erwartet, aber ein Aufruf an einer beliebigen Stelle von einem der Rückrufe von mqtt löst dies aus

Code: Select all

  File "/opt/cameras/./cams.py", line 33, in on_connect
stream("garage", 10)
~~~~~~^^^^^^^^
File "/opt/cameras/./cams.py", line 64, in stream
render = ImageTk.PhotoImage(load)
File "/home/htpc/.local/lib/python3.14/site-packages/PIL/ImageTk.py", line 129, in __init__
self.__photo = tkinter.PhotoImage(**kw)
~~~~~~~~~~~~~~~~~~^^^^^^
File "/usr/lib64/python3.14/tkinter/__init__.py", line 4301, in __init__
Image.__init__(self, 'photo', name, cnf, master, **kw)
~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib64/python3.14/tkinter/__init__.py", line 4248, in __init__
self.tk.call(('image', 'create', imgtype, name,) + options)
~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
_tkinter.TclError: image type "photo"  does not exist
cams.py

Code: Select all

#!/usr/bin/env python3

"""
Listen for mqtt events from frigate and show them on the htpc
"""

import sys
import json
from threading import Thread
from io import BytesIO
from tkinter import Tk, Label
#from tkinter import *
from PIL import Image, ImageTk
import paho.mqtt.client as mqtt
import requests

FRIGATE_API = ""
MQTT_SERVER = ""
MQTT_USERNAME = ""
MQTT_PASSWORD = ""

size = 540,540

WIN = Tk()
WIN.overrideredirect(True)
LABEL = Label(WIN)
LABEL.place(x=0, y=0)
LABEL.pack()

def on_connect(client, userdata, flags, rc, properties):
"""
connect callback
"""
stream("", 10) #just here for testing
del userdata, flags, properties
print(f"MQTT connected {rc}")
client.subscribe("frigate/events")

def on_message(client, userdata, msg):
"""
message callback
"""
del client, userdata
event = msg.payload
event = json.loads(event.decode())
if event['before']['stationary'] is False:
if 'front' in event['before']['current_zones']:
stream(event['before']['camera'], 10)

def stream(camera, i):
"""
do the actual drawing
"""
url = f"{FRIGATE_API}/{camera}/latest.jpg"
if i == -1:
WIN.withdraw()
else:
WIN.deiconify()
frame = requests.get(url, timeout=1)
load = Image.open(BytesIO(frame.content))
load.thumbnail(size, Image.Resampling.LANCZOS)
render = ImageTk.PhotoImage(load)
LABEL.configure(image=render)
LABEL.image = render
WIN.after(1000, stream, camera, i-1)

def main():
"""
main
"""
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
client.username_pw_set(MQTT_USERNAME, MQTT_PASSWORD)
client.on_connect = on_connect
client.on_message = on_message
client.connect(MQTT_SERVER, 1883, 60)
print("dispatch client thread")
client_loop = Thread(target=client.loop_forever, daemon=True)
client_loop.start()
print("start tk main loop")
WIN.mainloop()

if __name__ == '__main__':
sys.exit(main())

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post