我在python中的两个脚本之间传递变量时遇到问题而没有结束导入的脚本。我想更新我的tkinter GUI中的状态栏以反映script2中的计数器所在的数字。我已经包含以下代码:
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将是:
#script2
import time
def information():
variable = 0
while variable < 500:
yield variable
variable += 1
print(variable)
time.sleep(1)
我知道这与Generators有关,但我的理解是Yield会暂停循环,将数据发送到原始程序,让它处理它,然后取消循环。有没有更好的方法来理解这个过程?
谢谢你的时间!
答案 0 :(得分:0)
您的information
生成器返回一个迭代器,您需要保存迭代器实例并在其上调用next()
以获取下一个值。要更改var
,您需要使用.set()
进行更改。
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()
script2
可以保持不变。但是我建议你不使用time.sleep
,它不会像你期望的那样工作!这只会使你的程序在给定的秒数内没有响应。
如果你想增加直到StopIteration,你需要使用root.after
,只需将runScript
改为此::
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)
答案 1 :(得分:0)
首先,script2.information()
是一个生成器函数,这意味着您必须手动迭代在第一次调用时返回的生成器对象以获取连续值。
另一方面,tkinter
不支持多线程。您可以做的一件事是使用通用窗口小部件方法after()
计划在一定时间后调用函数。在这种情况下,它可以用于调度对(添加的)函数的调用,该函数在通过调用script2.information()
创建生成器对象之后对其进行迭代,并且每次都相应地更新StringVar()
小部件它被称为。
您还需要更改script2.py
,以便它不会调用time.sleep()
。这样做会使你的tkinter GUI程序在被调用时挂起(因为它暂时中断了tkinter mainloop()
的执行)。
修改后的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
主脚本:
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()