从python中的另一个函数结束函数中的循环

时间:2015-05-24 05:17:25

标签: python loops python-3.x global-variables

是否可以在python中结束另一个函数的函数循环? 这似乎不起作用

这是我的代码:

from tkinter import*
root = Tk()
def loop():
    global superman
    superman=False
    while superman==False:
        print("It's doing something")
def endloop():
    global superman
    superman=True

btn_1 = Button(root, text="stop", command=endloop)
btn_1.pack()
btn_2 = Button(root, text="start", command=loop)
btn_2.pack()

2 个答案:

答案 0 :(得分:3)

这里的问题是你的WHERE (AccountId(CASE(AccountId) WHEN 99999 THEN <>124 ELSE =@accountId)) 循环只是继续运行,这意味着你的其余代码都无法运行。这包括Tkinter GUI,这意味着您的程序不会响应任何用户事件,包括按钮点击,因此while永远不会被调用。

更一般地说,你真的不能拥有一个只能在GUI程序中永久运行,甚至超过几分之一秒的功能。单线程程序一次只能做一件事;如果它正在做的是永远循环,那么它就没有做任何其他事情了。

那么,可以你做什么?

有两个基本选项:

  1. 将循环放在后台线程上。这意味着现在必须显式同步任何共享数据,这意味着循环不能触及任何GUI小部件 - 但在您的情况下,结果非常简单。

  2. 打破循环。让它只进行一次迭代(或者说,100次迭代,如果它们真的很快),然后使用endloopafter要求Tkinter调用另一次迭代的函数(或100次迭代)和after_idle再次,依此类推,直到他们全部完成。

  3. 我会告诉你如何在这里做第一个。

    after

    对于唯一共享数据是“停止”标记的情况,import threading from tkinter import* root = Tk() def real_loop(): while True: with superman_lock: if not superman: return print("It's doing something") def loop(): global superman global superman_lock superman=False superman_lock = threading.Lock() thread = threading.Thread(target=real_loop, daemon=True) def endloop(): global superman with superman_lock: superman=True btn_1 = Button(root, text="stop", command=endloop) btn_1.pack() btn_2 = Button(root, text="start", command=loop) btn_2.pack() Condition通常优于Eventthreading文档解释了不同类型的同步对象之间的差异,但并不是真正的介绍级别。关于monitors的维基百科文章可能是一个更好的学习起点,但是如果你能找到一个关于多线程的好教程(不一定是特定于Python的; Python与C pthreads库有基本相同的同步对象,那么C ++提升库,Java stdlib等等,可能会更好。

    有关更详细的讨论,请参阅Why your GUI app freezes

答案 1 :(得分:1)

假设你的loop()函数在后台做了一些工作,将它放在一个单独的线程中是个好主意。 使用线程事件,您可以与线程进行交互。

此代码未经过测试,但它应该让您了解我在某些情况下如何解决此类问题:

class Worker(threading.Thread):
    def __init__(self):
        threading.Thread.__init__()

        self.run_event = threading.Event()

    def run(self):
        self.run_event.wait()

        while self.run_event.is_set():
            print "It's doing something!"

然后你可以初始化线程,它会在启动后立即调用run()方法,并在第一行中等待run_event设置。

假设您有一个引用工作线程的全局变量,那么从按钮触发的loop()方法将如下所示:

def loop():
    global worker_thread
    worker_thread.run_event.set()

通过设置run_event,传递self.run_event.wait()并输入工作循环。只要设置了线程事件,此while循环就会运行。

你的endloop()可能看起来像这样:

dev endloop():
    global worker_thread
    worker_thread.run_event.clear()

一旦清除线程中的run_event,就不再满足while条件并退出循环。

请注意: 此代码不完整也未经过测试,但可能会让您知道如何完成。别忘了

import threading

希望这会有所帮助。 格尔茨