python - Python 2.7,thread.Timer 产生了太多没有回收的垃圾线程
问题描述
我在我的windows上运行一个python示例代码,每次执行定时器线程后,都会创建一个新线程,如下所示,但旧线程从未回收过,线程数量不断增加真的很烦人,我担心我的软件迟早会消耗整个 PC 内存。我看到很多人也遇到了同样的问题,用pydev调试时,最终会报“ TclError: out of stack space ”!
这是我的pydev调试堆栈列表,它会越来越多,直到“堆栈空间不足”,从堆栈视图中,我看到线程数非常疯狂......
Thread-1913 - pid_9200_id_155817632
Thread-1915 - pid_9200_id_156052840
Thread-1917 - pid_9200_id_156052112
Thread-1919 - pid_9200_id_156326208
Thread-1921 - pid_9200_id_156326264
pydev 报错如下:
pydev debugger: starting (pid: 9200)
Exception in thread Thread-1921:
Traceback (most recent call last):
File "C:\Python27\lib\threading.py", line 801, in __bootstrap_inner
self.run()
File "C:\Python27\lib\threading.py", line 1073, in run
self.function(*self.args, **self.kwargs)
File "D:\work\tools\eclipseWorkspace\timerTest.py", line 46, in handle_function
self.hFunction()
File "D:\work\tools\eclipseWorkspace\timerTest.py", line 56, in printer
lab['text'] = clock
File "C:\Python27\lib\lib-tk\Tkinter.py", line 1337, in __setitem__
self.configure({key: value})
File "C:\Python27\lib\lib-tk\Tkinter.py", line 1330, in configure
return self._configure('configure', cnf, kw)
File "C:\Python27\lib\lib-tk\Tkinter.py", line 1321, in _configure
self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))
TclError: out of stack space (infinite loop?)
下面是我的代码,它设置一个计时器,然后调用函数“循环”函数
from threading import Timer, Thread, Event
from datetime import datetime
import Tkinter as tk
app = tk.Tk()
lab = tk.Label(app, text="Timer will start in a sec")
lab.pack()
class perpetualTimer():
def __init__(self, t, hFunction):
self.t = t
self.hFunction = hFunction
self.thread = Timer(self.t, self.loop)
def loop(self):
self.hFunction()
self.thread = Timer(self.t, self.loop)
self.thread.start()
def start(self):
self.thread.start()
def printer():
tempo = datetime.today()
clock = "{}:{}:{}".format(tempo.hour, tempo.minute, tempo.second)
try:
lab['text'] = clock
except RuntimeError:
exit()
t = perpetualTimer(0.1, printer)
t.start()
app.mainloop()
解决方案
您的代码不会在我的 Python 上执行。一旦 Timer 线程被触发,就无需取消它。只做一个新的。此外,将第一个 Timer 创建放在初始化例程中并等待它执行处理函数要干净得多:
class perpetualTimer():
def __init__(self, t, hFunction):
self.t = t
self.hFunction = hFunction
self.thread = Timer(self.t, self.handle_function)
def handle_function(self):
self.hFunction()
self.thread = Timer(self.t, self.handle_function)
self.thread.start()
def start(self):
self.thread.start()
所有 Timer 线程在它们触发后终止,稍后将被垃圾收集。它们不会填满所有可用的内存。
推荐阅读
- java - 用户日志为空
- mysql - LoadError: 无法加载此类文件 -- mysql2/mysql2 - on rake db:create
- c# - 检测程序集的特定版本是否在 GAC 中
- r - 查看数据框时rstudio中未对齐的列
- typescript - TypeScript: How do you specify an inlined object's type?
- php - 如何根据是否找到数据修改 PHP SQL SELECT 查询以显示消息
- reactjs - React Facebook 登录 - 登录后隐藏按钮
- c# - 正确使用 Environment.ExitCode = -1
- excel - 从找到的值中删除整个列
- python-3.x - 如何从 Boto3 中的文件路径中删除前缀