Python 加速潜在的长任务
我决定创建一个类,以便在Tkinter中轻松显示动画GIF,这确实可行,但动态收集所有帧的过程通常需要花费大量的时间,并在完成之前防止任何其他事情发生。我想知道是否有什么方法可以加快速度,或者用一种更有效的方法来做同样的事情 下面是该类的代码:Python 加速潜在的长任务,python,tkinter,Python,Tkinter,我决定创建一个类,以便在Tkinter中轻松显示动画GIF,这确实可行,但动态收集所有帧的过程通常需要花费大量的时间,并在完成之前防止任何其他事情发生。我想知道是否有什么方法可以加快速度,或者用一种更有效的方法来做同样的事情 下面是该类的代码: from tkinter import * class animation: def __init__(self,*args,**kwargs): self.root=args[0] self.label=Lab
from tkinter import *
class animation:
def __init__(self,*args,**kwargs):
self.root=args[0]
self.label=Label(self.root)
self.label.grid()
self.image=kwargs["image"]
try:
self.delay=kwargs["delay"]
except KeyError:
self.delay=20
self.frames=[]
x=0
while True:
try:
img=PhotoImage(file=self.image,
format="gif -index {}".format(x))
self.frames.append(img)
x+=1
except:
break
def animate(self,y):
try:
self.label.configure(image=self.frames[y])
self.root.after(self.delay,lambda:self.animate(y+1))
except IndexError:
self.label.configure(image=self.frames[0])
self.root.after(self.delay,lambda:self.animate(1))
下面是它的使用方法:
from tkinter import *
from modules.animation import animation
root=Tk()
cosmog=animation(root,image="cosmog.gif").animate(0)
cosmoem=animation(root,image="cosmoem.gif").animate(0)
lunala=animation(root,image="lunala.gif").animate(0)
root.mainloop()
在线程方面尝试以下操作:
import threading
import time
def __init__(self, *args, **kwargs):
self.frames=[]
self.run_loop = True
self.x=0
self.taken = []
self.order = []
while self.run_loop:
threading.Thread(target=self.add_image).start()
def add_image(self):
try:
if self.x not in self.taken: # make sure not several threads add the same image index
self.taken.append(self.x)
self.x+=1
else:
return
# save local x before creating image, for the order
# all the other threads will increment self.x while Image is created
x = self.x
img=PhotoImage(file=self.image, format="gif -index {}".format(self.x))
self.frames.append(img)
self.order.append(x) # keep track of the order
if len(self.frames) == len(self.taken): # when finish
self.frames = [x for _,x in sorted(zip(self.order,self.frames))] # sort the frames to the order
except:
self.run_loop = False
我制作了一个没有tkinter的简单可运行示例,使用time.sleep(随机时间量)来模拟PhotoImage:
import threading
import time
from random import randint
class Test:
frames=[]
run_loop = True
x=0
taken = []
order = []
time = 0
def __init__(self):
while self.run_loop:
threading.Thread(target=self.add_image).start()
def add_image(self):
if self.x < 100:
if self.x not in self.taken: # make sure not several threads add the same image index
self.taken.append(self.x)
self.x+=1
else:
return
x = self.x
t = randint(1,10)/10.0
self.time += t
time.sleep(t) # PhotoImage random time.sleep 0 to 1 second
self.order.append(x)
self.frames.append(x)
if len(self.frames) == len(self.taken):
print("Frames before sort")
print(self.frames)
self.frames = [x for _,x in sorted(zip(self.order,self.frames))]
print("\nFrames after sort")
print(self.frames)
print("\nTime used combined: {} seconds".format(self.time))
else:
self.run_loop = False
t = Test()
导入线程
导入时间
从随机导入randint
课堂测试:
帧=[]
运行循环=真
x=0
采取=[]
订单=[]
时间=0
定义初始化(自):
当self.run\u循环时:
threading.Thread(target=self.add_image).start()
def添加_图像(自身):
如果self.x<100:
如果self.x不在self.take中:#确保没有几个线程添加相同的图像索引
self.take.append(self.x)
self.x+=1
其他:
返回
x=自我。x
t=randint(1,10)/10.0
自身时间+=t
时间。睡眠(t)#照片图像随机时间。睡眠0到1秒
self.order.append(x)
self.frames.append(x)
如果len(self.frames)=len(self.take):
打印(“排序前的帧”)
打印(自帧)
self.frames=[x表示ux,x表示已排序(zip(self.order,self.frames))]
打印(“\n排序后的帧”)
打印(自帧)
打印(“\n使用的时间组合:{}秒”。格式(self.time))
其他:
self.run\u循环=False
t=测试()
此测试显示使用的组合时间约为50秒。对于100个线程,它可以在1秒内完成。最长时间的时间量。睡眠时间为0到1秒。
因此,对于您来说,在开始tkinter之前,不应该花费超过一个最长的
PhotoImage
call或者创建读取所有图像的类。或者使用线程读取文件。这不会有多大帮助,但您应该加载一次图像,然后拉出所有帧,而不是从HDD加载每一帧的图像。另外,请注意创建tkinter小部件的正确方法:对当前小部件进行子类化。这样,您就可以像对待代码中的任何其他小部件一样对待它(pack、grid、tkraise等)。FWIW,而不是self.root.after(self.delay,lambda:self.animate(1))
您可以使用self.root.after(self.delay,self.animate,1)
谢谢大家的帮助