【问题标题】:Pass a variable between two scripts?在两个脚本之间传递一个变量?
【发布时间】:2017-10-16 06:45:59
【问题描述】:

我在 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 会暂停循环,将数据发送到原始程序,让它处理它,然后取消暂停循环。有没有更好的方法来理解这个过程?

【问题讨论】:

    标签: python tkinter scripting statusbar yield


    【解决方案1】:

    一方面,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()
    

    【讨论】:

      【解决方案2】:

      您的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)
      

      【讨论】:

      • 感谢您的回复!但是,当我进行您建议的更改时,我的状态栏变为“”,并且 script2 中的循环不会继续。
      • 另外,我只在其他脚本中投入时间来模拟一些困难且耗时的事情。不过,我很欣赏这方面的信息!
      • 它对我来说很好用。你有没有把我的代码改成这样:var.set(information())?你需要做的正是我所做的。
      • 每次按下按钮时它都会增加吗?还是一次遍历一个数字,直到循环完成,有点像进度表?我正在努力实现后者。我认为我解释得不好。
      • 好吧,你还想用发电机吗?生成器在“每次按下按钮时递增”的情况下工作得非常好,因为生成器在遇到 yield 时会暂停,并在再次调用 next() 时继续......但对于后者,我认为没有必要
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-06
      • 1970-01-01
      • 2023-01-19
      • 1970-01-01
      • 2019-09-12
      • 1970-01-01
      相关资源
      最近更新 更多