python3 Timer 内存泄漏

发布于 2022-09-13 00:20:50 字数 944 浏览 11 评论 0

发现我如下使用Timer会出现内存泄漏,程序运行起来,内存使用量快速增加,不会减少。这段代码在tkinter界面中,若用tkinter.after将Timer替换,内存泄漏就不存在了。如何使用Timer才是正确的姿势?谢谢!

from threading import Timer, Thread
from queue import Queue
import time

def opWork():
    while True:
        if not opQueue.empty():
            opQueue.get()
            print(" -------------- pocess a cmd!")
        else:
            time.sleep(0.001)

def tickOff():
    opQueue.put("cmd")
    global tick
    tick.cancel()
    tick = Timer(0.001, tickOff)      
    tick.start()
    print("add a cmd! -------------- ")

tick = Timer(0.001, tickOff)  

if __name__ == "__main__":
    opQueue = Queue()

    worker = Thread(target=opWork)
    worker.start()

    tick.start()


是python本身的bug吗?刚找到这个 [issue43050] threading timer memory leak

问题代码如下:

While True:
    timer = threading.Timer(5, None)
    timer.start()
    timer.cancel()

我试了,内存快速增加,不会减少。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

书信已泛黄 2022-09-20 00:20:50

通过测试 while True: timer.start&cancel&join, threading.Timer 确实存在内存泄露。

查看 threading.Timer 的实现,它本质上是 thread, 即使不存在内存泄露,这么高频繁地创建/销毁thread, 带来的cpu开销也很大;
同时 Queue(maxsize) 要设定个最大值避免queue无限堆积,或者使用 collections.deque, 不过 queue.get(block: bool) 可以设置是否block (也因此get前不用判断是否empty, 也不用 sleep); deque.get() 是 non-blocking, 需要使用threading.condition来避免 busy loop.

题主可能真正需要的是一个 ticker,使用一个线程就够用了

# 伪代码
class Ticker(Thread):
    queue: Queue
    interval: float
    stop: Event
    
    def run():
        put_in_queue = self.queue.put
        interval = self.interval
        stopped = self.stop.is_set
        
        while True:
            if stopped():
                break
                
            put_in_queue('something')
            // 如果 consumer 先退出,可能导致 put 永远 block
            // 由于 put 会 block, 需要根据具体需求处理 put 花费的时间,决定 interval 具体值
            sleep(interval)
弥枳 2022-09-20 00:20:50
def tickOff():
    opQueue.put("cmd")
    global tick
    tick.cancel()
    tick = Timer(0.001, tickOff)      
    tick.start()
    print("add a cmd! -------------- ")

tick = Timer(0.001, tickOff) 自己在调自己 无限递归

from threading import Timer, Thread
from queue import Queue
import time

def opWork():
    while True:
        if not opQueue.empty():
            opQueue.get()
            print(" -------------- pocess a cmd!")
        else:
            time.sleep(0.001)

def tickOff():
    opQueue.put("cmd")

if __name__ == "__main__":
    opQueue = Queue()

    worker = Thread(target=opWork)
    worker.start()

    while 1:
      tickOff()
      time.sleep(1)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文