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

Thi*_*oln 5 python loops global-variables python-3.x

在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()
Run Code Online (Sandbox Code Playgroud)

aba*_*ert 3

这里的问题是你的while循环一直在运行,这意味着你的代码的其余部分都不会运行。这包括 Tkinter GUI,这意味着您的程序不会响应任何用户事件,包括按钮单击,因此endloop永远不会被调用。

\n\n

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

\n\n

所以,你可以做什么?

\n\n

有两个基本选项:

\n\n
    \n
  1. 将循环放在后台线程上。这意味着现在必须显式同步任何共享数据,并且意味着循环不能触及任何 GUI 小部件\xe2\x80\x94,但就您而言,事实证明这非常简单。

  2. \n
  3. 打破循环。让它只执行一次迭代(或者说 100 次迭代,如果它们真的很快的话),然后使用afterafter_idle要求 Tkinter 调用一个执行另一次迭代(或 100 次迭代)的函数,然后after再次执行,如此继续,直到全部完成。

  4. \n
\n\n

我将在这里向您展示如何执行第一个操作。

\n\n
import threading\nfrom tkinter import*\nroot = Tk()\n\ndef real_loop():\n    while True:\n        with superman_lock:\n            if not superman:\n                return\n       print("It\'s doing something")\ndef loop():\n    global superman\n    global superman_lock\n    superman=False\n    superman_lock = threading.Lock()\n    thread = threading.Thread(target=real_loop, daemon=True)\ndef endloop():\n    global superman\n    with superman_lock:\n        superman=True\n\nbtn_1 = Button(root, text="stop", command=endloop)\nbtn_1.pack()\nbtn_2 = Button(root, text="start", command=loop)\nbtn_2.pack()\n
Run Code Online (Sandbox Code Playgroud)\n\n

对于唯一共享数据是“停止”标志的情况,ConditionEvent通常比 更好Lock。这些threading文档解释了不同类型的同步对象之间的差异,但并不是真正的介绍性级别。关于监视器的维基百科文章可能是一个更好的学习起点,但是如果您能找到关于多线程的好教程(不一定是特定于 Python 的;Python 具有与 C pthreads 库、C++ Boost 库、 Java stdlib 等),那可能会更好。

\n\n

有关更详细的讨论,请参阅为什么 GUI 应用程序冻结

\n

  • @ThierryLincoln:请仔细阅读。我没有说这会让 Tkinter 崩溃,而且也不会。它_将_做的是让 Tkinter 停止响应事件。这意味着你的“endloop”函数永远不会被调用。这就是为什么它不会杀死循环。 (3认同)