Seite 1 von 1
Benutzerspeicher wächst
Verfasst: Dienstag 18. November 2008, 16:37
von Robin
Hallo Python-Forum,
habe mit folgendem Programm das Problem, dass der Benutzerspeicher ständig wächst, ca. 100k pro Minute, aber da das Programm Tag und Nacht laufen soll, ist es ein Problem. Wer kann helfen?
Code: Alles auswählen
import thread
def beenden():
sys-.exit(-1)
def endlosschleife():
.
# Daten grafisch darstellen
.
root=TK()
# Daten einlesen
thread.start_new_thread(endlosschleife,())
button=Buttom(root,text="Beenden",command=beenden)
root.mainloop()
Verfasst: Dienstag 18. November 2008, 17:11
von BlackJack
Der Benutzerspeicher wächst!? Das wäre ja mal ein tolles Programm. Bei mir ist der immer gleich, eben was ich da an RAM in den Rechner gesteckt habe.
Aber ich glaub's auch aus einem anderen Grund nicht: Das Programm lässt sich nicht einmal kompilieren weil es syntaktisch nicht korrekt ist.
Wäre es das, würde einem ein `NameError` um die Ohren fliegen.
Dann darf man auf eine (Tk-)GUI nur aus dem Thread zugreifen, in dem auch die Tk-Hauptschleife läuft, sonst kann alles mögliche passieren.
Und das interessante in `endlosschleife()` unterschlägst Du. So kann man nur raten, dass Du wahrscheinlich in der Funktion endlos Objekte erzeugst.
Verfasst: Dienstag 18. November 2008, 17:14
von lunar
Mit diesem Programm hast du mit Sicherheit gar keine Speicherprobleme, weil es nicht mal ein gültiges Programm ist. Und selbst wenn es das wäre, in 18 Zeilen unvollständigen Codes kann niemand ein Speicherleck finden.
Verfasst: Dienstag 18. November 2008, 17:24
von wuf
Hallo Robin
Hier nur die startfähige Version (war nicht einfach):
Code: Alles auswählen
import Tkinter as tk
import thread
import sys
def beenden():
sys.exit(-1)
def endlosschleife():
# Daten grafisch darstellen
print 'Hallo'
pass
root=tk.Tk()
# Daten einlesen
thread.start_new_thread(endlosschleife,())
button=tk.Button(root,text="Beenden",command=beenden)
button.pack()
root.mainloop()
Gruss wuf
Verfasst: Dienstag 18. November 2008, 17:34
von wuf
Hallo Robin
Hier eine start- und lauffähige Variante (ohne Modul 'thread'):
Code: Alles auswählen
import Tkinter as tk
#import thread
import sys
def beenden():
sys.exit(-1)
def endlosschleife():
# Daten grafisch darstellen (alle 100ms)
print 'Hallo'
root.after(100, endlosschleife)
root=tk.Tk()
# Daten einlesen
#thread.start_new_thread(endlosschleife,())
endlosschleife()
button=tk.Button(root,text="Beenden",command=beenden)
button.pack()
root.mainloop()
Gruss wuf
Verfasst: Dienstag 18. November 2008, 19:32
von wuf
Hallo Robin
Hier ist noch etwas zum herumexperimentieren:
Code: Alles auswählen
import Tkinter as tk
import sys
from threading import Thread
from time import sleep
from random import randint
class Gui(object):
IMAGE =\
"""
R0lGODlhVABUAIQQAAAAACkTEzMYGEEeHkwjI1gpKWMuLnA0NHo5OYU+PpFE
RJxISKdOTr1YWMhdXd9oaP//////////////////////////////////////
/////////////////////////yH+FUNyZWF0ZWQgd2l0aCBUaGUgR0lNUAAh
+QQBAAAQACwAAAAAVABUAAAF/iAkjmRpnmiqrmzrvnAsz3Rt33iu73zv/8Cg
cEgsGo/IpHLJbDqf0Kh0Sq3mANisdsvlBqwiwIBALpvP6HLiK+2633CtE2Co
E+oGAEFPBjwGD4EPdAGCgAMNiYoNA0NdJAAJkpMJenx7fwOaA4SGf4uKjSNe
OJdkbGGUk5ZlfoCCnYGHoImiYWeoNXR4BrmRqpV7rX+Cg72eiLS2ELt4uTQA
CNLSX1rAwZeuxbHEyaCcWMzT1KUM5uYBWJq/qqx9mZvcs8rmWefoN1gO+/sB
AgAFCrCj5A7Tq0DyPinbB+Afv34AdGEqFmBPnYGrhL07aKyQLIXfEE4UFEDB
Mhh0/vxQtJjnWkFtWDoio8VIpEqSDk6+SFnsQcVdGCW9/APgAANOxz56W/TK
Us8AOaHlecoyaKVBwzgxYJRwaSibT//oAvDQQQAEQF1i3ZiJmMduNAcwdPgw
gM4YAO4xSBcNrdpsxDy9nfetHha9z2YACMC4MbMsagFt3KTJ50xlm5g1ZnxX
sYA+kCI/eNcz0GCQTCF93pPvjS2r2kaLoUz58rdRrmU0vMOrzmvRshPQCgxX
2ahrkjqrgPMbWOw/wkERJ5w6TG68Ch4o2M7d5HHn02nXVhp3VPbSjHSf7769
eTvipeNTD2U+fnrsgnq7Jwg/fs/5tYxiACWC3IfSeQ8k/qBde9+9x5F/xQBo
IAAIKhiIgTtVGAiDqYD3IITkGReGhhcqlwKFglio3X6r9AdicbeNmGKBJqKA
YiAqTgjci7ZVxwyJD2Dowo0J0tggfx+CKOFrQArZApE5vjaAhzxGiFotTM5Y
onopJoBAAga8dpSDVfbISFRhDPhllFyi91oDY7aYJITUySWWjG7qhsVmfC0D
AJxTCuWikiDZ6eeem6mjmAEINEJHoyb8GedzVc5jqAlnhSmOpotC+uhdkk5J
KY+zXBopAppGw6lujDraqo2AjvriIaaemiqqNZ746qcnwumKeMDWVqutjuIq
laev2vjnTWUis5yxquZq467Jup6QUrDYirdCtJtKay21kE4bLjMEHBATSYU4
+eytq+IFrnK83vLoZggsEIC6KWRabLt4ZTYbvNVawug49d7rrQh2acJMZkX8
O0q5WAxsb7oHg6GHub00Zq8D+IJho0Xj2Nuxx9ZCLDHFJO9Urk+NbZnykyv3
xHHFJF/c08gvl2CzIDPnrPIBgfTs85BYHJCTwkM/mcc6/CY9rSh00Pxy1GlK
nfJsYSDt9NZcd+3112CHLfbYZJdtdhQhAAA7
"""
def __init__(self):
self.window = tk.Tk()
self.window.title('The Invaders')
self.window.protocol("WM_DELETE_WINDOW", self.stop_it)
self.window.configure(bg='steelblue')
self.canvas = tk.Canvas(self.window, width=350, height=250, bg='black')
self.canvas.pack(expand='yes')
for image_obj in xrange(15):
ImageObject(self, self.IMAGE)
self.stop_button = tk.Button(self.window, fg='red',
font=('helvetica',12,'bold'), bd=1, highlightthickness=0,
text='Please stop it !!!', command=self.stop_it)
self.stop_button.pack(side='bottom', pady=4)
self.window.mainloop()
def stop_it(self):
sys.exit(0)
class ImageObject(Thread):
def __init__(self, gui, image):
Thread.__init__(self)
self.gui = gui
self.plane = gui.canvas
self.image = tk.PhotoImage(data=image)
self.id = self.plane.create_image(100, 100, image=self.image)
self.__restart()
self.start()
def __restart(self):
self.plane.coords(self.id, randint(0,250), randint(30, 100))
self.xpos = randint(-2, 2)
self.ypos = randint(1, 3)
def run(self):
while 1:
sleep(0.05)
self.plane.move(self.id, self.xpos, self.ypos)
if self.plane.coords(self.id)[1] > 150:
self.__restart()
def main():
gui = Gui()
if __name__ == "__main__":
main()
Gruss wuf
Verfasst: Dienstag 18. November 2008, 22:58
von yipyip
Hallo wuf,
Du hast genau das passende Beispiel
für das Mysterium "Threads" gebracht.
Die entscheidenden Parameter sind
ja Anzahl der Image-Objekte und die
Zeit für sleep() in der run() Methode.
Erniedrigt man die Zeit für 'sleep()' und erhöht
die Anzahl der Objekte (also Threads)
so wird die Animation immer stockender
und es kann bis zum Einfrieren kommen.
Nehme ich extreme Werte
-- sleep(0.001), #Threads = 111 --
so erscheint zwar das Tk-Fenster, aber der Inhalt ist
der des Desktops dahinter.
Da ist wohl der GIL für verantwortlich?
yipyip
P.S.
*Thumbs Up* für alle Deine Beispiele,
insbesondere für Deine faszinierende
Amateurfunk-Gui
Verfasst: Mittwoch 19. November 2008, 10:39
von wuf
Hallo yipyip
yipyip hat geschrieben:Hallo wuf,
Nehme ich extreme Werte
-- sleep(0.001), #Threads = 111 --
so erscheint zwar das Tk-Fenster, aber der Inhalt ist
der des Desktops dahinter.
Ja damit kannst du dein Software-Prozessor einem 'Leistungs EKG-Test' aussetzen.
yipyip hat geschrieben:
P.S.
*Thumbs Up* für alle Deine Beispiele,
insbesondere für Deine faszinierende
Amateurfunk-Gui
Danke für deine motivierenden Worte
@Robin
Hier eventuell eine Start-Variante für einen Thread-Test. Betreffs Memory-Verbrauch könnte vielleicht das Problem auch im grafischen Teil deines Programms liegen:
Code: Alles auswählen
import Tkinter as tk
import sys
from threading import Thread
from time import sleep
class Gui(object):
def __init__(self):
#~~ Erzeuge das Hauptfenster
self.window = tk.Tk()
self.window.title('Thread-Test')
self.window.protocol("WM_DELETE_WINDOW", self.stop_it)
self.window.configure(bg='steelblue')
#~~ Erzeuge das Tread-Object
self.my_thread_obj = TreadObject("Robin")
#~~ Erzeuge die Stop Schaltflaeche
self.stop_button = tk.Button(self.window, fg='red',
font=('helvetica',12,'bold'), bd=1, highlightthickness=0,
text='Stop', command=self.stop_it)
self.stop_button.pack(side='bottom', pady=4)
self.window.mainloop()
def stop_it(self):
"""Thread-Test beenden"""
sys.exit(0)
class TreadObject(Thread):
def __init__(self, name):
"""Konstruktor fuer ThreadObject"""
self.name = name
#~~ Initialisiere die geerbte Klasse Thread
Thread.__init__(self)
#~~ Starte die Endlosschleife ueber die Thread-Methode 'run'
self.start()
def run(self):
"""Endlosschleife"""
while 1:
sleep(0.1)
print "Hallo %s" % self.name
# Hier Daten grafisch darstellen
def main():
gui = Gui()
if __name__ == "__main__":
main()
Gruss wuf
Verfasst: Mittwoch 19. November 2008, 11:20
von Robin
Hi WUF,
oh, ja, Du hast recht, der Fehler muss im grafischen Teil liegen.
Im Thread wandle ich dauernd aktuelle png-Datein einer
RoundRobinDatabase in GIF-Dateien um, damit ich sie
mit Hilfe von Photoimage über Labels in Tkinter darstellen kann.
Wenn ich diesen Bereich auskommentiere, bleibt der Speicher
stabil. Mache ich hier etwas falsch oder kann ich anderweitig
PNG-Bilder mit Tkinter darstellen?
Code: Alles auswählen
im = Image.open('/data/system/test.png')
name = '/data/system/test.gif'
im.save(name, "gif")
imb= PhotoImage(width=600, height=240,file=name)
lblb=Label(root,image=imb)
lblb.grid(row=0,column=0)
Gruß Robin
Verfasst: Mittwoch 19. November 2008, 11:43
von BlackJack
Hör auf ständig neue `Label` zu erzeugen und ändere einfach bei *einem* Label die angezeigte Grafik, oder *zerstöre* die `Label`-Objekte auch explizit wieder.
Verfasst: Mittwoch 19. November 2008, 12:16
von wuf
Hallo Robin
Du kannst .PNG's verwenden sofern du das Packet PIL (Photo-Image-Library) installiert hast.
Hier ein kleines Testprogramm:
Code: Alles auswählen
import Tkinter as tk
import Image
import ImageTk
test_window = tk.Tk()
pil_icon = Image.open("my_image.png")
pil_icon_1 = pil_icon.rotate(45)
pil_icon_2 = pil_icon.resize((70,70))
tk_icon = ImageTk.PhotoImage(pil_icon)
tk_icon_1 = ImageTk.PhotoImage(pil_icon_1)
tk_icon_2 = ImageTk.PhotoImage(pil_icon_2)
button = tk.Button(test_window, image=tk_icon)
button.pack(side='left')
button = tk.Button(test_window, image=tk_icon_1)
button.pack(side='left')
button = tk.Button(test_window, image=tk_icon_2)
button.pack(side='left')
test_window.mainloop()
Es ist aber nicht möglich PNG's im BASE64-Format anzuzeigen!
Gruss wuf
Verfasst: Mittwoch 19. November 2008, 12:33
von wuf
Hallo Robin
Hier in etwa was 'BlackJack' gemeint hat:
Code: Alles auswählen
import Tkinter as tk
import sys
from threading import Thread
from time import sleep
class Gui(object):
def __init__(self):
#~~ Erzeuge das Hauptfenster
self.window = tk.Tk()
self.window.title('Thread-Test')
self.window.protocol("WM_DELETE_WINDOW", self.stop_it)
self.window.configure(bg='steelblue')
#~~ Erzeuge das Tread-Object
self.my_thread_obj = TreadObject(self.window, "Robin")
#~~ Erzeuge die Stop Schaltflaeche
self.stop_button = tk.Button(self.window, fg='red',
font=('helvetica',12,'normal'), bd=1, highlightthickness=0,
text='Stop', command=self.stop_it)
self.stop_button.pack(pady=4)
self.window.mainloop()
def stop_it(self):
"""Thread-Test beenden"""
sys.exit(0)
class TreadObject(Thread):
def __init__(self, parent, name):
"""Konstruktor fuer ThreadObject"""
self.parent = parent
self.name = name
#~~ Initialisiere die geerbte Klasse Thread
Thread.__init__(self)
#~~ Erzeugt das Label-Objekt
self.my_label = tk.Label(self.parent)
self.my_label.pack()
#~~ Starte die Endlosschleife ueber die Thread-Methode 'run'
self.start()
def run(self):
"""Endlosschleife"""
while 1:
sleep(0.1)
print "Hallo %s" % self.name
# my_image = tk.PhotoImage(width=600, height=240,file='help.gif') #'my_image.gif')
my_image = tk.PhotoImage(file='my_image.gif')
self.my_label.configure(image=my_image)
def main():
gui = Gui()
if __name__ == "__main__":
main()
Du musst nur noch das passende 'my_image.gif' zur Verfügung stellen.
Gruss wuf
Verfasst: Mittwoch 19. November 2008, 13:39
von Robin
Hi WUF und BlackJack,
ganz herzlichen Dank für Eure wertvollen Beiträge, ich denke sie sollten genügen,
damit ich ein funktionsfähiges Programm erzeugen kann. Zuerst probiere ich aus,
die Labels nicht immer wieder neu zu erzeugen. Wenn das nicht geht, nehme ich WUFs
letzten Sourcecode. Der sieht ja richtig gut aus!
Danke nochmals!
Robin