当列表长度增加时,FuncAnimation Plot 挂起
FuncAnimation Plot hangs when length of list increases
为了我的大学项目,我正在 python 中开发流量生成脚本。此流量生成脚本使用多处理模块以并发方式生成大量 http 流量。我的脚本工作正常,现在我正在尝试使用 wxpython 构建一个用户友好的 GUI 来操作这些脚本的工作。我保留了这两个脚本 separate.In 我的 GUI 脚本,我导入了我的流量生成(工作)脚本,然后调用它的函数(work.time_func() 或 work.requests_func())到 运行 由用户在 GUI 上启动时的多进程。到这里我的脚本工作正常。此外,在我的 wxpython 面板中,我附加了一个图表,绘制了一些与流量生成脚本相关的数据(各种进程之间的共享列表)( work.rt ( multiprocessing.Manager().list() )-->这实际上是所有进程之间共享的数据)。现在要在此处绘制的数据长度 (len(work.rt)) 增加到 1,00,00,000,但我的 GUI 在仅绘制大约 2500 个数据后挂起。这里可能是什么问题?如何克服呢?我正在使用 centos 6.5。这是我的代码:
import work #traffic generation script
import wx.lib.scrolledpanel as scrolled
import matplotlib.animation as anim
import matplotlib.figure as mfigure
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.backends.backend_wxagg import NavigationToolbar2WxAgg as NavigationToolbar
import time
import wx
import os
import paramiko
import sys
from paramiko import SSHConfig
from paramiko import SSHClient
from multiprocessing import Value
import thread
class TabPanel1(scrolled.ScrolledPanel):
def __init__(self,parent):
scrolled.ScrolledPanel.__init__(self,parent=parent)
self.SetDoubleBuffered(True)
self.label_0=wx.StaticText(self,-1,"Mode of Operation:",(40,25))
self.label_0_list=['Request Based','Time Based']
self.label_0_combo=wx.ComboBox(self,-1,'None',(200,25),wx.DefaultSize,self.label_0_list,wx.CB_DROPDOWN)
self.label_1=wx.StaticText(self,-1,"Number of Clients:",(40,75))
self.label_1_list=['1','2','3','4','5','10','15','20','25','30','35','40','45','50']
self.label_1_combo=wx.ComboBox(self,-1,'None',(200,75),wx.DefaultSize,self.label_1_list,wx.CB_DROPDOWN)
self.label_2=wx.StaticText(self,-1,"Actions:",(40,125))
self.label_2_list=['Web','Download','Video']
self.label_2_combo=wx.ComboBox(self,-1,'None',(200,125),wx.DefaultSize,self.label_2_list,wx.CB_DROPDOWN)
self.label_3=wx.StaticText(self,-1,"Number of Servers:",(40,175))
self.label_3_list=['1','2','3','4','5','6','7','8','9','10']
self.label_3_combo=wx.ComboBox(self,-1,'None',(200,175),wx.DefaultSize,self.label_3_list,wx.CB_DROPDOWN)
self.label_4=wx.StaticText(self,-1,"Size of File:",(40,225))
self.label_4_list=['small-files','0to1kb','10kb','20kb','50kb','70kb','100kb','200kb','500kb','700kb','1mb','2mb','video1.2mb','video2.2mb','video2mb','video3mb','allfiles']
self.label_4_combo=wx.ComboBox(self,-1,'None',(200,225),wx.DefaultSize,self.label_4_list,wx.CB_DROPDOWN)
self.label_5=wx.StaticText(self,-1,"RampUpTime(ms):",(40,275))
self.label_5_list=['500','750','1000','2000','5000']
self.label_5_combo=wx.ComboBox(self,-1,'None',(200,275),wx.DefaultSize,self.label_5_list,wx.CB_DROPDOWN)
self.label_6_list=['1minute','5minutes','10minutes','15minutes','30minutes','1hour','2hours','3hours','4hours','5hours','6hours','10hours','12hours','15hours','18hours','24hours','Mode is Request Based']
self.label_6=wx.StaticText(self,-1,"Test Time:",(40,325))
self.label_6_combo=wx.ComboBox(self,-1,'None',(200,325),wx.DefaultSize,self.label_6_list,wx.CB_DROPDOWN)
self.label_7_list=['10000','20000','40000','50000','70000','100000','200000','500000','700000','1000000','Mode is Time Based']
self.label_7=wx.StaticText(self,-1,"Number of Requests:",(40,375))
self.label_7_combo=wx.ComboBox(self,-1,'None',(200,375),wx.DefaultSize,self.label_7_list,wx.CB_DROPDOWN)
self.failed=wx.StaticText(self,-1,"Failed Requests:",(400,25))
self.result=wx.StaticText(self, label="",pos=(525,25))
self.result.SetForegroundColour(wx.RED)
self.scripttime=wx.StaticText(self,-1,"Script_Run_Time:",(400,50))
self.tresult=wx.StaticText(self, label="",pos=(525,75))
self.tresult.SetForegroundColour(wx.RED)
self.ok=wx.Button(self,label="OK",pos=(40,425))
self.ok.Bind(wx.EVT_BUTTON,self.onok)
self.cancle=wx.Button(self,label='Cancle',pos=(140,425))
self.cancle.Bind(wx.EVT_BUTTON,self.oncancle)
self.run=wx.Button(self,label="RUN",pos=(240,425))
self.run.Bind(wx.EVT_BUTTON,self.onrun)
self.cap=wx.Button(self,label="Capture",pos=(340,425))
self.cap.Bind(wx.EVT_BUTTON,self.oncap)
self.testcomplete=wx.Button(self,label="Test Complete",pos=(440,425))
self.testcomplete.Bind(wx.EVT_BUTTON,self.oncomplete)
self.action=self.label_2_combo.GetValue()
self.xmax=len(work.rt) if len(work.rt)>100 else 100
self.xmin=self.xmax-100
self.myfig=mfigure.Figure(dpi=50)
self.axes=self.myfig.add_subplot(111)
self.axes.set_xbound(lower=self.xmin,upper=self.xmax)
self.canvas=FigureCanvas(self,-1,self.myfig)
self.canvas.SetPosition((400,100))
self.toolbar=NavigationToolbar(self.canvas)
self.toolbar.Realize()
self.toolbar.SetPosition((400,75))
tw,th=self.toolbar.GetSizeTuple()
fw,fh=self.canvas.GetSizeTuple()
self.toolbar.SetSize(wx.Size(fw,th))
self.toolbar.update()
self.animator=anim.FuncAnimation(self.myfig,self.animator,interval=1000,repeat=True)
self.SetupScrolling()
def onok(self,event):
self.mode=self.label_0_combo.GetValue()
self.noc=int(self.label_1_combo.GetValue())
work.noc=self.noc
self.action=self.label_2_combo.GetValue()
if (self.action=='Web'):
work.action=Value('i',0)
elif(self.action=='Download'):
work.action=Value('i',1)
elif(self.action=='Video'):
work.action=Value('i',2)
else:
self.label_2=wx.StaticText(self,-1,"Please restart & select proper Action",(40,475))
self.Close()
self.nos=int(self.label_3_combo.GetValue())
work.nos=Value('i',self.nos)
self.filesize=self.label_4_combo.GetValue()
if (self.filesize=='small-files'):
work.low=Value('i',0)
work.high=Value('i',1)
elif (self.filesize=='0to1kb'):
work.low=Value('i',1)
work.high=Value('i',2)
elif (self.filesize=='10kb'):
work.low=Value('i',2)
work.high=Value('i',3)
elif (self.filesize=='20kb'):
work.low=Value('i',3)
work.high=Value('i',4)
elif (self.filesize=='50kb'):
work.low=Value('i',4)
work.high=Value('i',5)
elif (self.filesize=='70kb'):
work.low=Value('i',5)
work.high=Value('i',6)
elif (self.filesize=='100kb'):
work.low=Value('i',6)
work.high=Value('i',7)
elif (self.filesize=='200kb'):
work.low=Value('i',7)
work.high=Value('i',8)
elif (self.filesize=='500kb'):
work.low=Value('i',8)
work.high=Value('i',9)
elif (self.filesize=='700kb'):
work.low=Value('i',9)
work.high=Value('i',10)
elif (self.filesize=='1mb'):
work.low=Value('i',10)
work.high=Value('i',11)
elif (self.filesize=='2mb'):
work.low=Value('i',11)
work.high=Value('i',12)
elif (self.filesize=='video1.2mb'):
work.low=Value('i',12)
work.high=Value('i',13)
elif (self.filesize=='video2.2mb'):
work.low=Value('i',13)
work.high=Value('i',14)
elif (self.filesize=='video2mb'):
work.low=Value('i',14)
work.high=Value('i',15)
elif (self.filesize=='video3mb'):
work.low=Value('i',15)
work.high=Value('i',16)
elif (self.filesize=='allfiles'):
work.low=Value('i',0)
work.high=Value('i',16)
else:
self.label_2=wx.StaticText(self,-1,"Please restart & select proper file size",(40,475))
self.Close()
self.rampuptime=int(self.label_5_combo.GetValue())
work.rampuptime=(self.rampuptime/1000)
self.mytime=self.label_6_combo.GetValue()
if (self.mytime=='1minute'):
self.testtime=60.0
elif (self.mytime=='5minutes'):
self.testtime=300.0
elif (self.mytime=='10minutes'):
self.testtime=600.0
elif (self.mytime=='15minutes'):
self.testtime=900.0
elif (self.mytime=='30minutes'):
self.testtime=1800.0
elif (self.mytime=='1hour'):
self.testtime=3600.0
elif (self.mytime=='2hours'):
self.testtime=7200.0
elif (self.mytime=='3hours'):
self.testtime=10800.0
elif (self.mytime=='4hours'):
self.testtime=14400.0
elif (self.mytime=='5hours'):
self.testtime=18000.0
elif (self.mytime=='6hours'):
self.testtime=21600.0
elif (self.mytime=='10hours'):
self.testtime=36000.0
elif (self.mytime=='12hours'):
self.testtime=43200.0
elif (self.mytime=='15hours'):
self.testtime=54000.0
elif (self.mytime=='18hours'):
self.testtime=64800.0
elif (self.mytime=='24hours'):
self.testtime=86400.0
elif (self.mytime=='Mode is Request Based'):
work.end_time=0
else:
self.label_2=wx.StaticText(self,-1,"Please restart & select proper test time",(40,475))
self.Close()
self.nor=self.label_7_combo.GetValue()
def oncancle(self,event):
sys.exit()
def oncap(self,event):
os.system("gnome-terminal -e 'tcpdump -ni eth0 port 80 -w cap.pcap'")
def onrun(self,event):
time.sleep(1)
self.scriptstart=float(time.time())
self.mode=self.label_0_combo.GetValue()
if (self.mode=='Time Based'):
work.end_time=time.time()+self.testtime
thread.start_new_thread(work.time_func, ())
elif(self.mode=='Request Based'):
work.number_of_requests=int(self.nor)
thread.start_new_thread(work.requests_func, ())
def oncomplete(self,event):
self.label_2=wx.StaticText(self,-1,"All work Done..!! To generate traffic again, Please restart the script ",(40,475))
x=len(work.rt)
y=work.scriptend-self.scriptstart
self.result.SetLabel("Errors=%d/%d"%(work.error_count.value,x))
self.tresult.SetLabel("%f"%y)
def animator(self,i):
self.axes.cla()
self.axes.set_ylabel("Response Time")
self.axes.set_xlabel("Number of Files")
return self.axes.plot(work.rt)
class DemoFrame(wx.Frame):
def __init__ (self):
wx.Frame.__init__(self,None,wx.ID_ANY,"Python_Scripts",size=(800,500))
self.mypanel=TabPanel1(self)
self.SetDoubleBuffered(True)
self.Layout()
self.Centre()
self.Show()
def onexit(self,event):
sys.exit()
if __name__=='__main__':
app=wx.App(False)
frame=DemoFrame()
frame.Show()
app.MainLoop()
找到解决方案,
使用 wx.calllater 而不是动画图形,即不是使用间隔时间为 1000 毫秒的 funcanimation,首先调用简单绘制 canvas 的绘图函数,然后在该函数内提供 wx.calllater 在每 1000 毫秒调用一次的结束
例如
main_function():
plot_function()
plot_function(self):
<plotting of graph>
wx.CallLater(1000,self.plot_function)
为了我的大学项目,我正在 python 中开发流量生成脚本。此流量生成脚本使用多处理模块以并发方式生成大量 http 流量。我的脚本工作正常,现在我正在尝试使用 wxpython 构建一个用户友好的 GUI 来操作这些脚本的工作。我保留了这两个脚本 separate.In 我的 GUI 脚本,我导入了我的流量生成(工作)脚本,然后调用它的函数(work.time_func() 或 work.requests_func())到 运行 由用户在 GUI 上启动时的多进程。到这里我的脚本工作正常。此外,在我的 wxpython 面板中,我附加了一个图表,绘制了一些与流量生成脚本相关的数据(各种进程之间的共享列表)( work.rt ( multiprocessing.Manager().list() )-->这实际上是所有进程之间共享的数据)。现在要在此处绘制的数据长度 (len(work.rt)) 增加到 1,00,00,000,但我的 GUI 在仅绘制大约 2500 个数据后挂起。这里可能是什么问题?如何克服呢?我正在使用 centos 6.5。这是我的代码:
import work #traffic generation script
import wx.lib.scrolledpanel as scrolled
import matplotlib.animation as anim
import matplotlib.figure as mfigure
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.backends.backend_wxagg import NavigationToolbar2WxAgg as NavigationToolbar
import time
import wx
import os
import paramiko
import sys
from paramiko import SSHConfig
from paramiko import SSHClient
from multiprocessing import Value
import thread
class TabPanel1(scrolled.ScrolledPanel):
def __init__(self,parent):
scrolled.ScrolledPanel.__init__(self,parent=parent)
self.SetDoubleBuffered(True)
self.label_0=wx.StaticText(self,-1,"Mode of Operation:",(40,25))
self.label_0_list=['Request Based','Time Based']
self.label_0_combo=wx.ComboBox(self,-1,'None',(200,25),wx.DefaultSize,self.label_0_list,wx.CB_DROPDOWN)
self.label_1=wx.StaticText(self,-1,"Number of Clients:",(40,75))
self.label_1_list=['1','2','3','4','5','10','15','20','25','30','35','40','45','50']
self.label_1_combo=wx.ComboBox(self,-1,'None',(200,75),wx.DefaultSize,self.label_1_list,wx.CB_DROPDOWN)
self.label_2=wx.StaticText(self,-1,"Actions:",(40,125))
self.label_2_list=['Web','Download','Video']
self.label_2_combo=wx.ComboBox(self,-1,'None',(200,125),wx.DefaultSize,self.label_2_list,wx.CB_DROPDOWN)
self.label_3=wx.StaticText(self,-1,"Number of Servers:",(40,175))
self.label_3_list=['1','2','3','4','5','6','7','8','9','10']
self.label_3_combo=wx.ComboBox(self,-1,'None',(200,175),wx.DefaultSize,self.label_3_list,wx.CB_DROPDOWN)
self.label_4=wx.StaticText(self,-1,"Size of File:",(40,225))
self.label_4_list=['small-files','0to1kb','10kb','20kb','50kb','70kb','100kb','200kb','500kb','700kb','1mb','2mb','video1.2mb','video2.2mb','video2mb','video3mb','allfiles']
self.label_4_combo=wx.ComboBox(self,-1,'None',(200,225),wx.DefaultSize,self.label_4_list,wx.CB_DROPDOWN)
self.label_5=wx.StaticText(self,-1,"RampUpTime(ms):",(40,275))
self.label_5_list=['500','750','1000','2000','5000']
self.label_5_combo=wx.ComboBox(self,-1,'None',(200,275),wx.DefaultSize,self.label_5_list,wx.CB_DROPDOWN)
self.label_6_list=['1minute','5minutes','10minutes','15minutes','30minutes','1hour','2hours','3hours','4hours','5hours','6hours','10hours','12hours','15hours','18hours','24hours','Mode is Request Based']
self.label_6=wx.StaticText(self,-1,"Test Time:",(40,325))
self.label_6_combo=wx.ComboBox(self,-1,'None',(200,325),wx.DefaultSize,self.label_6_list,wx.CB_DROPDOWN)
self.label_7_list=['10000','20000','40000','50000','70000','100000','200000','500000','700000','1000000','Mode is Time Based']
self.label_7=wx.StaticText(self,-1,"Number of Requests:",(40,375))
self.label_7_combo=wx.ComboBox(self,-1,'None',(200,375),wx.DefaultSize,self.label_7_list,wx.CB_DROPDOWN)
self.failed=wx.StaticText(self,-1,"Failed Requests:",(400,25))
self.result=wx.StaticText(self, label="",pos=(525,25))
self.result.SetForegroundColour(wx.RED)
self.scripttime=wx.StaticText(self,-1,"Script_Run_Time:",(400,50))
self.tresult=wx.StaticText(self, label="",pos=(525,75))
self.tresult.SetForegroundColour(wx.RED)
self.ok=wx.Button(self,label="OK",pos=(40,425))
self.ok.Bind(wx.EVT_BUTTON,self.onok)
self.cancle=wx.Button(self,label='Cancle',pos=(140,425))
self.cancle.Bind(wx.EVT_BUTTON,self.oncancle)
self.run=wx.Button(self,label="RUN",pos=(240,425))
self.run.Bind(wx.EVT_BUTTON,self.onrun)
self.cap=wx.Button(self,label="Capture",pos=(340,425))
self.cap.Bind(wx.EVT_BUTTON,self.oncap)
self.testcomplete=wx.Button(self,label="Test Complete",pos=(440,425))
self.testcomplete.Bind(wx.EVT_BUTTON,self.oncomplete)
self.action=self.label_2_combo.GetValue()
self.xmax=len(work.rt) if len(work.rt)>100 else 100
self.xmin=self.xmax-100
self.myfig=mfigure.Figure(dpi=50)
self.axes=self.myfig.add_subplot(111)
self.axes.set_xbound(lower=self.xmin,upper=self.xmax)
self.canvas=FigureCanvas(self,-1,self.myfig)
self.canvas.SetPosition((400,100))
self.toolbar=NavigationToolbar(self.canvas)
self.toolbar.Realize()
self.toolbar.SetPosition((400,75))
tw,th=self.toolbar.GetSizeTuple()
fw,fh=self.canvas.GetSizeTuple()
self.toolbar.SetSize(wx.Size(fw,th))
self.toolbar.update()
self.animator=anim.FuncAnimation(self.myfig,self.animator,interval=1000,repeat=True)
self.SetupScrolling()
def onok(self,event):
self.mode=self.label_0_combo.GetValue()
self.noc=int(self.label_1_combo.GetValue())
work.noc=self.noc
self.action=self.label_2_combo.GetValue()
if (self.action=='Web'):
work.action=Value('i',0)
elif(self.action=='Download'):
work.action=Value('i',1)
elif(self.action=='Video'):
work.action=Value('i',2)
else:
self.label_2=wx.StaticText(self,-1,"Please restart & select proper Action",(40,475))
self.Close()
self.nos=int(self.label_3_combo.GetValue())
work.nos=Value('i',self.nos)
self.filesize=self.label_4_combo.GetValue()
if (self.filesize=='small-files'):
work.low=Value('i',0)
work.high=Value('i',1)
elif (self.filesize=='0to1kb'):
work.low=Value('i',1)
work.high=Value('i',2)
elif (self.filesize=='10kb'):
work.low=Value('i',2)
work.high=Value('i',3)
elif (self.filesize=='20kb'):
work.low=Value('i',3)
work.high=Value('i',4)
elif (self.filesize=='50kb'):
work.low=Value('i',4)
work.high=Value('i',5)
elif (self.filesize=='70kb'):
work.low=Value('i',5)
work.high=Value('i',6)
elif (self.filesize=='100kb'):
work.low=Value('i',6)
work.high=Value('i',7)
elif (self.filesize=='200kb'):
work.low=Value('i',7)
work.high=Value('i',8)
elif (self.filesize=='500kb'):
work.low=Value('i',8)
work.high=Value('i',9)
elif (self.filesize=='700kb'):
work.low=Value('i',9)
work.high=Value('i',10)
elif (self.filesize=='1mb'):
work.low=Value('i',10)
work.high=Value('i',11)
elif (self.filesize=='2mb'):
work.low=Value('i',11)
work.high=Value('i',12)
elif (self.filesize=='video1.2mb'):
work.low=Value('i',12)
work.high=Value('i',13)
elif (self.filesize=='video2.2mb'):
work.low=Value('i',13)
work.high=Value('i',14)
elif (self.filesize=='video2mb'):
work.low=Value('i',14)
work.high=Value('i',15)
elif (self.filesize=='video3mb'):
work.low=Value('i',15)
work.high=Value('i',16)
elif (self.filesize=='allfiles'):
work.low=Value('i',0)
work.high=Value('i',16)
else:
self.label_2=wx.StaticText(self,-1,"Please restart & select proper file size",(40,475))
self.Close()
self.rampuptime=int(self.label_5_combo.GetValue())
work.rampuptime=(self.rampuptime/1000)
self.mytime=self.label_6_combo.GetValue()
if (self.mytime=='1minute'):
self.testtime=60.0
elif (self.mytime=='5minutes'):
self.testtime=300.0
elif (self.mytime=='10minutes'):
self.testtime=600.0
elif (self.mytime=='15minutes'):
self.testtime=900.0
elif (self.mytime=='30minutes'):
self.testtime=1800.0
elif (self.mytime=='1hour'):
self.testtime=3600.0
elif (self.mytime=='2hours'):
self.testtime=7200.0
elif (self.mytime=='3hours'):
self.testtime=10800.0
elif (self.mytime=='4hours'):
self.testtime=14400.0
elif (self.mytime=='5hours'):
self.testtime=18000.0
elif (self.mytime=='6hours'):
self.testtime=21600.0
elif (self.mytime=='10hours'):
self.testtime=36000.0
elif (self.mytime=='12hours'):
self.testtime=43200.0
elif (self.mytime=='15hours'):
self.testtime=54000.0
elif (self.mytime=='18hours'):
self.testtime=64800.0
elif (self.mytime=='24hours'):
self.testtime=86400.0
elif (self.mytime=='Mode is Request Based'):
work.end_time=0
else:
self.label_2=wx.StaticText(self,-1,"Please restart & select proper test time",(40,475))
self.Close()
self.nor=self.label_7_combo.GetValue()
def oncancle(self,event):
sys.exit()
def oncap(self,event):
os.system("gnome-terminal -e 'tcpdump -ni eth0 port 80 -w cap.pcap'")
def onrun(self,event):
time.sleep(1)
self.scriptstart=float(time.time())
self.mode=self.label_0_combo.GetValue()
if (self.mode=='Time Based'):
work.end_time=time.time()+self.testtime
thread.start_new_thread(work.time_func, ())
elif(self.mode=='Request Based'):
work.number_of_requests=int(self.nor)
thread.start_new_thread(work.requests_func, ())
def oncomplete(self,event):
self.label_2=wx.StaticText(self,-1,"All work Done..!! To generate traffic again, Please restart the script ",(40,475))
x=len(work.rt)
y=work.scriptend-self.scriptstart
self.result.SetLabel("Errors=%d/%d"%(work.error_count.value,x))
self.tresult.SetLabel("%f"%y)
def animator(self,i):
self.axes.cla()
self.axes.set_ylabel("Response Time")
self.axes.set_xlabel("Number of Files")
return self.axes.plot(work.rt)
class DemoFrame(wx.Frame):
def __init__ (self):
wx.Frame.__init__(self,None,wx.ID_ANY,"Python_Scripts",size=(800,500))
self.mypanel=TabPanel1(self)
self.SetDoubleBuffered(True)
self.Layout()
self.Centre()
self.Show()
def onexit(self,event):
sys.exit()
if __name__=='__main__':
app=wx.App(False)
frame=DemoFrame()
frame.Show()
app.MainLoop()
找到解决方案, 使用 wx.calllater 而不是动画图形,即不是使用间隔时间为 1000 毫秒的 funcanimation,首先调用简单绘制 canvas 的绘图函数,然后在该函数内提供 wx.calllater 在每 1000 毫秒调用一次的结束 例如
main_function():
plot_function()
plot_function(self):
<plotting of graph>
wx.CallLater(1000,self.plot_function)