Pass a variable between two scripts?
For one thing, script2.information()
is a generator function which means you will have to manually iterate the generator object returned on the first call it to get successive values.
For another, tkinter
doesn't support multithreading. One thing you can do is schedule for a function to be called after a certain amount of time using the universal widget method after()
. In this case, it can be used to schedule a call to an (added) function that iterates the generator object after it's been created by calling script2.information()
and updates the StringVar()
widget accordingly each time it's called.
You also need to change script2.py
so it doesn't call time.sleep()
. Doing so will make your tkinter GUI program hang whenever it's called (since it temporarily interrupts execution of the tkinter mainloop()
).
Modified script2.py
:
import timedef 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
main script:
from tkinter import *import script2DELAY = 100 # in millisecsroot = 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 delaydef run_script(var): gen = script2.information() # create generator object do_update(gen, var) # start iterating generator and updating varvar = 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()
Your information
generator returns an iterator, you will need to save the iterator instance and call next()
on it to get the next value. To change the var
, you will need to use .set()
to change it.
from tkinter import *import script2root = 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 generatorinfo = 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()
The script2
can stay the same. But I recommend you to not use time.sleep
, it wouldn't work as you expect it to! It will just make your program not respond for the given seconds.
You will need to use root.after
if you want to increment to continue till StopIteration, just change runScript
to this::
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)