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

Pass a variable between two scripts?

我在 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)

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

您的 information 生成器 returns 一个迭代器,您将需要保存迭代器实例并对其调用 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,它不会像您期望的那样工作!它只会让您的程序在给定的秒数内不响应。

如果你想继续递增直到停止迭代,你将需要使用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)

首先,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()