Hallo,
ich möchte mit Hilfe eines Pythonscripts mit visa Messgeräte ansteuern.
Um die Übersichtlichkeit zu verbessern möchte ich außerdem mit Hilfe von TKinter eine GUI programmieren.
Was wäre die beste Methode, um zu verhindern, dass das Interface "einfriert", sobald bei der Messgerätkalibrierung Wartezeiten entstehen.
Vielen Dank für eure Hilfe!
Gruß,
Dominik
Nebenläufigkeit von GUI und Messgerätkalibrierung realisiere
@dominik123: Du könntest die Kalibrierung in einem eigenen Thread (`threading`-Modul) laufen lassen. Wichtig ist, dass man nur vom Hauptthread aus Veränderungen an der GUI vornehmen darf. Falls der Arbeitsthread etwas in der GUI verändern soll, dann verwendet man üblicherweise `Queue.Queue`-Objekte um zwischen den beiden Threads zu kommunizieren und fragt im Hauptthread mittels `after()`-Methode regelmässig ob neue Daten in der Queue vorliegen.
-
- User
- Beiträge: 35
- Registriert: Montag 10. Februar 2014, 08:48
Vielen Dank für die Antwort!
Zur Kalibrierung nutze ich momentan ein eigenes Script, das sehr umfangreich ist. Kann ich tatsächlich das gesamte Script als Thread aufrufen? Muss die Kalibrierung im gleichen Script ablaufen, wie die Erstellung des GUI?
Gruß,
Dominik
Zur Kalibrierung nutze ich momentan ein eigenes Script, das sehr umfangreich ist. Kann ich tatsächlich das gesamte Script als Thread aufrufen? Muss die Kalibrierung im gleichen Script ablaufen, wie die Erstellung des GUI?
Gruß,
Dominik
@dominik123: Du kannst streng genommen nicht das Skript als Thread aufrufen aber Du kannst einen Thread starten in dem das Skript dann aufgerufen wird. Wenn es tatsächlich als eigener Prozess laufen soll gibt es dafür das `subprocess`-Modul. Ansonsten würde ich versuchen das Skript so zu schreiben das man es auch als Modul importieren kann und darin dann die entsprechende Funktion(en) aufrufen kann.
-
- User
- Beiträge: 35
- Registriert: Montag 10. Februar 2014, 08:48
Ich habe versucht, dass Kalibierungsscript mithilfe der import- Funktion in das GUI zu importieren. Wenn ich nun allerdings mein GUI starten möchte, so öffnet sich nur die Kalibrierung und sobald diese fertig ist öffnet sich das GUI. Worauf muss ich achten, wenn ich das Script als Modul importieren möchte?
Wie kann ich denn das ganze Script mithilfe eines Threads aufrufen?
Vielen Dank!
Wie kann ich denn das ganze Script mithilfe eines Threads aufrufen?
Vielen Dank!
@dominik123: Du musst das Modul so schreiben das man es importieren kann ohne das es als Programm los läuft. Dafür wertet man in einem Modul `__name__` aus, was an den Modulnamen gebunden ist, ausser wenn man ein Modul direkt ausführt, dann ist es an den Wert '__main__' gebunden. Das Idiom sieht so aus:
Und in der `main()`-Funktion steht dann das Hauptprogramm.
Code: Alles auswählen
if __name__ == '__main__':
main()
-
- User
- Beiträge: 35
- Registriert: Montag 10. Februar 2014, 08:48
Vielen Dank!
Habe die Kalibrierung jetzt so umgeschrieben, dass ich sie als Modul importieren kann, ohne dass sie direkt los läuft.
Wenn ich nun jedoch (mittels Button) eine Funktion aus dem "Kalibrierungsmodul" aufrufe, friert mein GUI solange ein, bis diese Funktion vollständig abgearbeitet wurde. Hier kommt nun die eigentliche Nebenläufigkeit ins Spiel und diese bereitet mir immer noch Probleme!
Wie könnte ich eine Funktion wie z.B. "calibration.start_measurement()" in einen Thread auslagern, sodass mein GUI nicht mehr einfriert?
Mit dem Befehl thread.start_new_thread() komme ich momentan leider nicht weiter...
Habe die Kalibrierung jetzt so umgeschrieben, dass ich sie als Modul importieren kann, ohne dass sie direkt los läuft.
Wenn ich nun jedoch (mittels Button) eine Funktion aus dem "Kalibrierungsmodul" aufrufe, friert mein GUI solange ein, bis diese Funktion vollständig abgearbeitet wurde. Hier kommt nun die eigentliche Nebenläufigkeit ins Spiel und diese bereitet mir immer noch Probleme!
Wie könnte ich eine Funktion wie z.B. "calibration.start_measurement()" in einen Thread auslagern, sodass mein GUI nicht mehr einfriert?
Mit dem Befehl thread.start_new_thread() komme ich momentan leider nicht weiter...
@dominik123: Das `thread`-Modul sollte man sowieso nicht mehr verwenden, deshalb hatte ich ja auf das `threading`-Modul verwiesen.
So ganz allgemein ohne mehr zu wissen kann man nur das hier sagen:
Dann läuft die Funktion nebenläufig.
So ganz allgemein ohne mehr zu wissen kann man nur das hier sagen:
Code: Alles auswählen
thread = Thread(target=calibration.start_measurement)
thread.start()
-
- User
- Beiträge: 35
- Registriert: Montag 10. Februar 2014, 08:48
Hallo,
um eine Progressbar zu installieren habe ich folgende Funktion:
um sie nebenläufig ausführen zu lassen, habe ich sie folgendermaßen aufgerufen:
die Progressbar läuft auch los, allerdings wird folgende Fehlermeldung ausgegeben und das Programm beendet:
was ich nicht verstehe ist, dass die Progressbar überhaupt losläuft... wie kann ich diesen Fehler umgehen?
Vielen Dank!
um eine Progressbar zu installieren habe ich folgende Funktion:
Code: Alles auswählen
def progress():
progressbar = ttk.Progressbar(orient=HORIZONTAL, length=140, mode='indeterminate', maximum=10)
progressbar.grid(row=7, column=5, sticky=W)
progressbar.start(1000)
Code: Alles auswählen
Thread = thread(target=progress())
Thread.start()
Code: Alles auswählen
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python27\lib\lib-tk\Tkinter.py", line 1410, in __call__
return self.func(*args)
File "C:\Python27\GUI\GUI_1802.py", line 109, in consistency_check
Thread = thread(target=progress())
TypeError: 'module' object is not callable
Vielen Dank!
- pillmuncher
- User
- Beiträge: 1527
- Registriert: Samstag 21. März 2009, 22:59
- Wohnort: Pfaffenwinkel
1) Du sollst nicht das thread-Modul verwenden, sondern das threading-Modul. BlackJack hat dir das bereits mitgeteilt.
2) In threading gibt es eine Klasse Thread. Die musst du verwenden. Sie heißt nicht thread.
3) Das ganze tkinter-Zeugs muss im Haupt-Thread laufen. Aus einem zweiten Thread heraus direkt GUI-Manipulationen durchzuführen wird zu Problemen führen, weil tkinter, wie alle GUI Libs, bei sowas durcheinander kommt. Verwende dazu queue.Queue und verschicke darüber Nachrichten und Daten zwischen den einzelnen Threads.
4) Du musst die Funktion progress an Thread(...) übergeben. Statt dessen rufst du sie momentan auf und übergibst das Ergebnis dieses Aufrufs. Guckstu:
5) Es gibt eine Code-Formatierung im Forum. Verwende sie.
2) In threading gibt es eine Klasse Thread. Die musst du verwenden. Sie heißt nicht thread.
3) Das ganze tkinter-Zeugs muss im Haupt-Thread laufen. Aus einem zweiten Thread heraus direkt GUI-Manipulationen durchzuführen wird zu Problemen führen, weil tkinter, wie alle GUI Libs, bei sowas durcheinander kommt. Verwende dazu queue.Queue und verschicke darüber Nachrichten und Daten zwischen den einzelnen Threads.
4) Du musst die Funktion progress an Thread(...) übergeben. Statt dessen rufst du sie momentan auf und übergibst das Ergebnis dieses Aufrufs. Guckstu:
Code: Alles auswählen
>>> def foo():
... return 'hey!'
...
>>> foo
<function foo at 0x7fedda04>
>>> foo()
'hey!'
In specifications, Murphy's Law supersedes Ohm's.
-
- User
- Beiträge: 35
- Registriert: Montag 10. Februar 2014, 08:48
Zunächst mal vielen Dank für die Antworten.
Ich importiere nun das threading- Modul.
Ist folgender Code richtig, um die Funktion progress an Thread() zu übergeben?
Momentan sieht meine progress- Funktion folgender Maßen aus:
Ich hoffe meine Frage ist verständlich.
Ich importiere nun das threading- Modul.
Ist folgender Code richtig, um die Funktion progress an Thread() zu übergeben?
Code: Alles auswählen
thread= threading.Thread(target=progress)
thread.start()
momentan würde ich also ein Teil des tkinter- Zeugs in einen extra Thread auslagern. Wie könnte ich meine progressbar auslagern, ohne automatisch einen teil des tkinter- Zeugs auszulagern und ohne dass diese sobald länger rechnende Funktionen abgearbeitet werden einfriert?def progress():
progressbar = ttk.Progressbar(orient=HORIZONTAL, length=140, mode='indeterminate', maximum=10)
progressbar.grid(row=7, column=5, sticky=W)
progressbar.start(1000)
Ich hoffe meine Frage ist verständlich.
- pillmuncher
- User
- Beiträge: 1527
- Registriert: Samstag 21. März 2009, 22:59
- Wohnort: Pfaffenwinkel
Hier ein kurzes Beispiel:Es ist bloß auf die Schnelle und ohne viel Nachdenken zusammengehackt.
Code: Alles auswählen
try:
import Tkinter as tk # Python 2
import ttk
except ImportError:
import tkinter as tk # Python 3
import tkinter.ttk as ttk
from threading import Thread
from queue import Queue, Empty
import time
def make_progress(queue, maximum, step):
for i in range(maximum):
queue.put(1)
time.sleep(step)
class MainApp(tk.Frame):
def __init__(self, master, queue, maximum, update_interval):
self.queue = queue
self.update_interval = update_interval
tk.Frame.__init__(self, master)
self.progress = ttk.Progressbar(self, maximum=maximum)
self.progress.pack(expand=1, fill=tk.BOTH)
self.show_progress()
def show_progress(self):
try:
width = self.queue.get(False)
except Empty:
return
else:
self.progress.step(width)
self.update()
finally:
self.after(self.update_interval, self.show_progress)
if __name__ == '__main__':
q = Queue()
m = 10
u = 1
s = 2
t = Thread(target=make_progress, args=(q, m, s))
t.start()
root = tk.Tk()
app = MainApp(root, q, m, u)
app.pack(expand=1, fill=tk.BOTH)
root.mainloop()
t.join()
In specifications, Murphy's Law supersedes Ohm's.
-
- User
- Beiträge: 35
- Registriert: Montag 10. Februar 2014, 08:48
Vielen Dank! Jetzt läuft alles parallel...