如何在python中定期运行函数

2025-03-26 09:10:00
admin
原创
11
摘要:问题描述:我有一个简单的节拍器在运行,不知何故,当它的节拍较低时,它很好,但当它的节拍较高时,它就不一致且不稳定。我不知道发生了什么。我想尝试使用某种东西定期运行它。有办法吗?这是我的代码:class thalam(): def __init__(self,root,e): self....

问题描述:

我有一个简单的节拍器在运行,不知何故,当它的节拍较低时,它很好,但当它的节拍较高时,它就不一致且不稳定。我不知道发生了什么。我想尝试使用某种东西定期运行它。有办法吗?

这是我的代码:

class thalam():
    def __init__(self,root,e):
        self.lag=0.2
        self.root=root
        self.count=0
        self.thread=threading.Thread(target=self.play)
        self.thread.daemon=True
        self.tempo=60.0/120
        self.e=e
        self.pause=False
        self.tick=open("tick.wav","rb").read()
        self.count=0
        self.next_call = time.time()
    def play(self):
        if self.pause:
            return
        winsound.PlaySound(self.tick,winsound.SND_MEMORY)
        self.count+=1
        if self.count==990:
            self.thread=threading.Thread(target=self.play)
            self.thread.daemon=True
            self.thread.start()
            return

        self.next_call+=self.tempo
        new=threading.Timer(self.next_call-time.time(),self.play)
        new.daemon=True
        new.start()
    def stop(self):
        self.pause=True
        winsound.PlaySound(None,winsound.SND_ASYNC)
    def start(self):
        self.pause=False
    def settempo(self,a):
        self.tempo=a
class Metronome(Frame):
    def __init__(self,root):
        Frame.__init__(self,root)
        self.first=True
        self.root=root
        self.e=Entry(self)
        self.e.grid(row=0,column=1)
        self.e.insert(0,"120")
        self.play=Button(self,text="Play",command=self.tick)
        self.play.grid(row=1,column=1)
        self.l=Button(self,text="<",command=lambda:self.inc("l"))
        self.l.grid(row=0,column=0)
        self.r=Button(self,text=">",command=lambda:self.inc("r"))
        self.r.grid(row=0,column=2)
    def tick(self):
        self.beat=thalam(root,self.e)
        self.beat.thread.start()
        self.play.configure(text="Stop",command=self.notick)
    def notick(self):
        self.play.configure(text="Start",command=self.tick)
        self.beat.stop()
    def inc(self,a):
        if a=="l":
            try:
                new=str(int(self.e.get())-5)
                self.e.delete(0, END)
                self.e.insert(0,new)
                self.beat.settempo(60.0/(int(self.e.get())))
            except:
                print "Invalid BPM"
                return
        elif a=="r":
            try:
                new=str(int(self.e.get())+5)
                self.e.delete(0, END)
                self.e.insert(0,new)
                self.beat.settempo((60.0/(int(self.e.get()))))
            except:
                print "Invalid BPM"
                return

解决方案 1:

播放声音来模拟普通节拍器不需要“实时”功能。

看起来您使用 Tkinter 框架来创建 GUI。root.after()允许您延迟调用函数。您可以使用它来实现滴答:

def tick(interval, function, *args):
    root.after(interval - timer() % interval, tick, interval, function, *args)
    function(*args) # assume it doesn't block

tick()每毫秒function按给定时间运行。单个刻度的持续时间受精度影响,但从长远来看,稳定性仅取决于功能。args`intervalroot.after()timer()`

这是一个打印一些统计数据(240每分钟心跳次数)的脚本:

#!/usr/bin/env python
from __future__ import division, print_function
import sys
from timeit import default_timer
try:
    from Tkinter import Tk
except ImportError: # Python 3
    from tkinter import Tk

def timer():
    return int(default_timer() * 1000 + .5)

def tick(interval, function, *args):
    root.after(interval - timer() % interval, tick, interval, function, *args)
    function(*args) # assume it doesn't block

def bpm(milliseconds):
    """Beats per minute."""
    return 60000 / milliseconds

def print_tempo(last=[timer()], total=[0], count=[0]):
    now = timer()
    elapsed = now - last[0]
    total[0] += elapsed
    count[0] += 1
    average = total[0] / count[0]
    print("{:.1f} BPM, average: {:.0f} BPM, now {}"
          .format(bpm(elapsed), bpm(average), now),
          end='
', file=sys.stderr)
    last[0] = now

interval = 250 # milliseconds
root = Tk()
root.withdraw() # don't show GUI
root.after(interval - timer() % interval, tick, interval, print_tempo)
root.mainloop()

节奏仅相差一个节拍:在我的计算机上为 240±1。

模拟情况如下asyncio

#!/usr/bin/env python3
"""Metronome in asyncio."""
import asyncio
import sys


async def async_main():
    """Entry point for the script."""
    timer = asyncio.get_event_loop().time
    last = timer()

    def print_tempo(now):
        nonlocal last
        elapsed = now - last
        print(f"{60/elapsed:03.1f} BPM", end="
", file=sys.stderr)
        last = now

    interval = 0.250  # seconds
    while True:
        await asyncio.sleep(interval - timer() % interval)
        print_tempo(timer())


if __name__ == "__main__":
    asyncio.run(async_main())

请参阅演讲:Łukasz Langa - AsyncIO + 音乐

解决方案 2:

由于处理器需要与其他程序共享自身,因此执行任何需要时间精度的操作都非常困难。不幸的是,对于时间关键型程序,操作系统可以随时切换到另一个进程。这可能意味着它可能要经过明显的延迟后才能返回到您的程序。在导入时间之后使用time.sleep是一种更一致的方式来平衡蜂鸣声之间的时间,因为处理器切换的“理由”较少。虽然 Windows 上的睡眠默认粒度为 15.6 毫秒,但我认为您不需要播放超过 64Hz 的节拍。此外,您似乎正在使用多线程来尝试解决您的问题,但是,线程的 Python 实现有时会强制线程按顺序运行。这使得切换出您的进程的情况更加糟糕。

我认为最好的解决方案生成包含所需频率的节拍器蜂鸣声的声音数据。然后,您可以以操作系统可以理解的方式播放声音数据。由于系统知道如何以可靠的方式处理声音,因此您的节拍器可以正常工作。

很抱歉让您失望,但时间关键型应用程序非常困难,除非您愿意亲自处理您正在使用的系统。

解决方案 3:

我想告诉你,由于竞争条件,在时间方面你无法精确地控制线程(即使你正在使用锁和信号量!)。甚至我也遇到过这个问题。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1989  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1446  
  在当今快速发展的IT行业中,项目管理工具的选择对于项目的成功至关重要。随着技术的不断进步,项目经理们需要更加高效、灵活的工具来应对复杂的项目需求。本文将介绍2025年IT项目经理力推的10款管理工具,帮助您在项目管理中取得更好的成果。信创国产项目管理软件 - 禅道禅道是一款国产开源的项目管理软件,禅道开源版不限人数,功...
项目管理工具   0  
  在当今快速变化的商业环境中,项目管理软件已成为企业提升效率、优化资源分配和确保项目成功的关键工具。随着技术的不断进步,市场上涌现出众多功能各异的项目管理工具,每一款都有其独特的优势和适用场景。本文将深入评测2025年最受欢迎的10款项目管理软件,帮助您根据自身需求做出明智的选择。信创国产项目管理软件 - 禅道禅道是一款...
项目管理平台   2  
  产品开发效率对于企业的竞争力至关重要。在当今复杂多变的商业环境中,如何有效提升产品开发效率成为众多企业关注的焦点。产品生命周期管理(PLM)作为一种整合产品全生命周期信息的管理理念和技术,为提升产品开发效率提供了有力的支持。通过合理运用PLM,企业能够优化流程、加强协作、提高数据管理水平,从而实现产品开发的高效运作。接...
plm开发流程软件   3  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用