当列表长度增加时,FuncAnimation Plot会挂起

时间:2015-04-20 11:36:27

标签: python matplotlib wxpython python-multiprocessing

对于我的大学项目,我正在使用python开发流量生成脚本。此流量生成脚本利用多处理模块以并发方式生成大量的http流量。我的脚本工作正常,现在我正在尝试使用wxpython构建一个用户友好的GUI来操作这些脚本的工作。我已经将这两个脚本分开了。在我的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()

1 个答案:

答案 0 :(得分:0)

找到解决方案, 使用wx.calllater而不是动画图形,即不使用1000毫秒间隔时间的funcanimation,首先调用简单绘制画布的绘图函数,然后在该函数内提供wx.calllater,在每1000毫秒后调用自身 例如

main_function():
    plot_function()
plot_function(self):
    <plotting of graph>
    wx.CallLater(1000,self.plot_function)