2017-05-17 9 views
2

Ich habe Probleme beim Übergeben von Variablen zwischen zwei Skripten in Python, ohne das importierte Skript zu beenden. Ich möchte für die Statusleiste in meinem tkinter GUI aktualisieren, um zu reflektieren, auf welcher Zahl der Zähler in script2 ist. Ich habe den Code unten enthalten:Eine Variable zwischen zwei Skripten übergeben?

from tkinter import * 
import script2 

root = Tk() 
canvas = Canvas(root, width=300, height=300) 
canvas.pack() 

def runScript(): 
    var = script2.information() 

button1 = Button(root, text="Click Me!", command=runScript) 
button1.pack() 

var = StringVar() 
var.set('Waiting for Input...') 
status = Label(root, textvariable=var, bd=1, relief=SUNKEN, anchor=W) 
status.pack(side=BOTTOM, fill=X) 



root.mainloop() 

Script2 wäre:

#script2 
import time 

def information(): 
    variable = 0 
    while variable < 500: 
     yield variable 
     variable += 1 
     print(variable) 
     time.sleep(1) 

Ich verstehe, dass dies mit Generatoren zu tun hat, aber mein Verständnis war, dass Yield die Schleife unterbrechen würde, die Daten senden zu dem ursprünglichen Programm, lassen Sie es verarbeiten und dann die Schleife pausieren. Gibt es einen besseren Weg, diesen Prozess zu verstehen?

Danke für Ihre Zeit!

Antwort

0

Für eine Sache, script2.information() ist eine Generatorfunktion, die bedeutet, dass Sie manuell haben wird Iteriere das Generatorobjekt, das beim ersten Aufruf zurückgegeben wurde, um aufeinanderfolgende Werte zu erhalten.

Zum anderen unterstützt tkinter Multithreading nicht. Eine Sache, die Sie können tun, ist Zeitplan für eine Funktion nach einer bestimmten Zeit mit der universellen Widget-Methode aufgerufen werden after() aufgerufen werden. In diesem Fall kann es verwendet werden, um einen Aufruf an eine (hinzugefügte) Funktion zu planen, die das Generatorobjekt nach dem Erstellen durch Aufruf von script2.information() iteriert und das Widget StringVar() bei jedem Aufruf entsprechend aktualisiert.

Sie müssen auch ändern script2.py, so dass es time.sleep() nicht aufrufen. Dadurch wird Ihr tkinter-GUI-Programm bei jedem Aufruf hängen bleiben (da es die Ausführung des tkinter mainloop() vorübergehend unterbricht).

Modified script2.py:

import time 

def information(): 
    variable = 0 
    while variable < 60: # changed from 500 for testing 
     yield variable 
     variable += 1 
     print(variable) 
#  time.sleep(1) # don't call in tkinter programs 

Haupt-Skript:

from tkinter import * 
import script2 

DELAY = 100 # in millisecs 

root = Tk() 
canvas = Canvas(root, width=300, height=300) 
canvas.pack() 

def do_update(gen, var): 
    try: 
     next_value = next(gen) 
    except StopIteration: 
     var.set('Done!') 
    else: 
     var.set(next_value) 
     root.after(DELAY, do_update, gen, var) # call again after delay 

def run_script(var): 
    gen = script2.information() # create generator object 
    do_update(gen, var) # start iterating generator and updating var 

var = StringVar() 
var.set('Waiting for Input...') 

button1 = Button(root, text="Run script!", command=lambda: run_script(var)) 
button1.pack() 

status = Label(root, textvariable=var, bd=1, relief=SUNKEN, anchor=W) 
status.pack(side=BOTTOM, fill=X) 

root.mainloop() 
0

Ihr information Generator gibt einen Iterator zurück, Sie müssen die Iteratorinstanz speichern und next() darauf aufrufen, um den nächsten Wert zu erhalten. Um das var zu ändern, müssen Sie .set() verwenden, um es zu ändern.

from tkinter import * 
import script2 

root = Tk() 
canvas = Canvas(root, width=300, height=300) 
canvas.pack() 

def runScript(): 
    var.set(next(info)) # set the variable as the "next" result of the info generator 

info = script2.information() # the info is an iterator 

button1 = Button(root, text="Click Me!", command=runScript) 
button1.pack() 

var = StringVar() 
var.set('Waiting for Input...') 
status = Label(root, textvariable=var, bd=1, relief=SUNKEN, anchor=W) 
status.pack(side=BOTTOM, fill=X) 

root.mainloop() 

Die script2 kann das gleiche bleiben. Aber ich empfehle Ihnen nicht verwenden time.sleep, es würde nicht funktionieren, wie Sie es erwarten! Es wird nur Ihr Programm nicht für die angegebenen Sekunden reagieren.

Sie müssen root.after verwenden, wenn Sie bis StopIteration weiterhin erhöhen wollen, nur runScript dies ändern ::

def runScript(): 
    global info 
    try: 
     var.set(next(info)) # set the variable as the "next" result of the info generator 
    except StopIteration: 
     var.set('Finished') 
     info = script2.information() 
    else: 
     root.after(1, runScript) 
+0

Vielen Dank für die Antwort! Wenn ich Ihre vorgeschlagenen Änderungen mache, wird meine Statusleiste jedoch zu "" und die Schleife in script2 wird nicht fortgesetzt. – cloudfr0g

+0

Außerdem habe ich nur Zeit in das andere Skript gesteckt, um etwas Schwieriges und Zeitaufwendiges zu simulieren. Ich schätze das Nugget von Informationen darüber, obwohl! – cloudfr0g

+0

Es funktionierte gut für mich .. hast du meinen Code geändert: 'var.set (information())'? Sie müssen genau das tun, was ich getan habe. – abccd

Verwandte Themen