Python中time.sleep异常,需实现128次/秒函数执行且不影响OpenGL渲染
问题:Python实现稳定每秒128次执行的函数,同时不影响OpenGL渲染帧率
需求
需要实现一个每秒执行128次的函数,同时后台运行PyOpenGLTk的OpenGL上下文,保证渲染帧率不受影响。
初始实现代码
import time, threading run_counter = 0 def runner(): global run_counter while True: do_something() run_counter += 1 time.sleep(1/128) threading.Thread(target=runner).start()
执行次数统计代码
while True: print(run_counter) run_counter = 0 time.sleep(1)
遇到的问题
- 理论上
time.sleep(1/128)能让函数每秒执行128次,但实际统计只有64次。 - 后台运行基于PyOpenGLTk的OpenGL上下文,相关代码如下:
OpenGL画布类
class WindowGLTkCanvas(OpenGLFrame): def __init__(self, parent, root, size: Dimension = Dimension(100, 100), scale=1): OpenGLFrame.__init__(self, root, width=size.x, height=size.y) PynamicsObject.__init__(self, parent) self.parent = parent self.renderable = [] self.scale = scale self.texture_handler = {} self.width = size.x self.height = size.y self.frame = Routine(self, target=self.redraw) def initgl(self): Logger.info("Call: initgl") glViewport(0, 0, self.width, self.height) glClearColor(0, 0, 0, 0) # 设置投影矩阵 glMatrixMode(GL_PROJECTION) glLoadIdentity() glOrtho(0, self.width, self.height, 0, -1, 1) # 设置模型视图矩阵 glMatrixMode(GL_MODELVIEW) glLoadIdentity() glEnable(GL_TEXTURE_2D) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glEnable(GL_BLEND) #glEnable(GL_LINE_SMOOTH) def redraw(self): Logger.info("Call: draw") glClear(GL_COLOR_BUFFER_BIT) glFlush() #Logger.info("Call: drawend")
Tkinter包装类
class WindowGLTk(): def __init__(self, parent): super().__init__(parent) self.root = tk.Tk() self.gl_canvas = WindowGLTkCanvas(self, self.root, Dim(500, 500)) self.gl_canvas.pack(fill=tk.BOTH, expand=tk.YES) self.gl_canvas.animate = True self.parent._viewport = self #self.frame = Routine(self, self._tick, delay=tps_to_seconds(200)) def _tick(self): print("RENDER") #self.gl_canvas.redraw() def load(self): self.root.mainloop()
尝试的替代方案及问题
实现轮询式睡眠函数:
def sleep(seconds: float): a = time.time() b = a + seconds while time.time() < b: pass return
该方案能让目标函数稳定每秒执行128次,但会导致PyOpenGLTk的redraw函数帧率远低于预期的144FPS。
自行解决的方案
采用定时批量启动任务的方式,虽显繁琐但有效:
def _loop(self): while True: for i in range(128): threading.Timer(i / 128, self.target).start() time.sleep(1)
内容的提问来源于stack exchange,提问作者relizc
相关产品推荐
相关产品推荐

