调用 tkinter.after(function) 一次又一次会导致堆栈溢出吗?

huangapple go评论66阅读模式
英文:

Will calling tkinter.after(function) over and over cause a stackoverflow?

问题

I'm creating a GUI that shows data that I want to be updated every 10 seconds with tkinter.

Now you can't use

import tkinter as tk
import time

master = tk.Tk()

while True:
    master.show(global variable that has been changed from a different thread)
    time.sleep(10)

master.mainloop()

because the mainloop would never run. Now a solution would be to put the code in a function and call that function with master.after() like this

import tkinter as tk

master = tk.Tk()

def updateValue():
    master.show(global variable that has been changed from a different thread)
    master.after(10000, updateValue)

updateValue()
master.mainloop()

Now I'm wondering if this would cause a stackoverflow issue because recursively calling a function over and over would, right?

Also, if this is not an issue, is it because the after method from tkinter takes care of it, or is Python optimizing for tail recursion?

Edit: I tried it, and using the tkinter.after method, it seems to run forever while it would fail after roughly 1000 calls with normal recursion. I would still be interested in why and how that is if anybody has an idea.

英文:

I'm creating a GUI that shows data that I want to be updated every 10 seconds with tkinter.

Now you can't use

import tkinter as tk
import time

master = tk.Tk()

while True:
    master.show(global variable that has been changed from different thread)
    time.sleep(10)

master.mainloop()

because the mainloop would never run. Now a solution would be to put the code in a function and call that function with master.after() like this

import tkinter as tk

master = tk.Tk()

def updateValue():
    master.show(global variable that has been changed from different thread)
    master.after(10000, updateValue)

updateValue()
master.mainloop()

Now I'm wondering if this would cause a stackoverflow issue because recursively calling a function over and over would, right?

Also if this is not an issue is it because the after method from tkinter takes care of it or is python optimizing for tail recursion?

Edit: I tried it and using the tkinter.after method it seems to run forever while it would fail after roughly 1000 calls with normal recursion. I would still be interested in why and how that is if anybody has an idea.

答案1

得分: 1

使用tkinter.after(function)反复调用会导致堆栈溢出吗?

当正确使用时,不会导致堆栈溢出。不过,如果你每秒调度某些操作运行一个月或一年,最终可能会耗尽内存。

现在我在想,这样会导致堆栈溢出问题,因为不断递归调用一个函数会导致堆栈溢出,对吗?

不断递归调用一个函数会导致堆栈溢出,但这并不是你使用after的方式。使用after并不在技术上是递归。使用after只是将某些操作添加到队列中。每次调用该函数时,都会从队列中移除一个项目。根据你的代码,假设没有其他代码调用after,那么队列永远不会变得比1更大。

如果这不是一个问题,是因为tkinter的after方法处理了它,还是因为Python进行了尾递归优化?

这是由内嵌的tcl解释器处理的,Python在这里没有进行优化。而且再次强调,这并不是递归。

英文:

> Will calling tkinter.after(function) over and over cause a stackoverflow?

When done properly, no. Though, if you're scheduling something every second to run in a month or year, you might eventually run out of memory.

> Now I'm wondering if this would cause a stackoverflow issue because recursively calling a function over and over would, right?

Recursively calling a function over and over would, but that's not what you're doing with after. Using after isn't technically recursion. With after, all you're doing is adding something to a queue. Each time the function is called, an item is removed from the queue. With your code, and assuming there's no other code calling after, the queue never gets any bigger than 1.

> Also if this is not an issue is it because the after method from tkinter takes care of it or is python optimizing for tail recursion?

It's being taken care of by the embedded tcl interpreter. Python does no optimization here. And again, this isn't recursion.

huangapple
  • 本文由 发表于 2023年3月9日 18:28:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/75683322.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定