Python 在两个脚本之间传递变量?

Python 在两个脚本之间传递变量?,python,tkinter,scripting,statusbar,yield,Python,Tkinter,Scripting,Statusbar,Yield,我在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

我在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.py
将是:

#script2
import time

def information():
    variable = 0
    while variable < 500:
        yield variable
        variable += 1
        print(variable)
        time.sleep(1)
#脚本2
导入时间
def信息():
变量=0
变量<500时:
产量变量
变量+=1
打印(变量)
时间。睡眠(1)

我知道这与生成器有关,但我的理解是,
yield
将暂停循环,将数据发送到原始程序,让它处理,然后取消暂停循环。有更好的方法来理解这个过程吗?

您的
信息
生成器返回一个迭代器,您需要保存迭代器实例并调用它的
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
可以保持不变。但是我建议你不要使用时间。睡眠,它不会像你期望的那样工作!它只会使你的程序在给定的几秒钟内没有响应

您将需要使用
根目录。在
之后,如果您想继续递增直到停止迭代,只需将
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)

首先,
script2.information()
是一个生成器函数,这意味着您必须手动迭代第一次调用时返回的生成器对象,以获得连续的值

另一方面,
tkinter
不支持多线程。您可以做的一件事是使用universal widget方法安排在一定时间后调用函数。在这种情况下,可以使用它来计划对(添加的)函数的调用,该函数在通过调用
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

谢谢你的回复!但是,当我做出您建议的更改时,我的状态栏变为“”,script2中的循环不会继续。此外,我只在另一个脚本中花费时间来模拟一些困难和耗时的事情。不过,我很感激这方面的宝贵信息!这对我很管用。。您是否将我的代码更改为:
var.set(information())
?你需要做的和我做的完全一样。每次你按下按钮它都会增加吗?或者它是一次一个地通过数字直到循环结束,有点像一个进度表?我正在努力实现后者。我想我解释得不好。好吧,那你还想用发电机吗?生成器在“每次按下按钮时递增”的情况下工作得非常好,因为生成器在遇到收益时会暂停,在再次调用next()时会继续。。。。但对于后者,我认为没有必要
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()