Python脚本冻结没有明显的原因(afaik)

时间:2011-01-09 13:26:56

标签: python matplotlib

我在python上并不是特别新,但我只是觉得这个程序可能没有正常工作的原因。我已经写了一个类似的,从中得到了,这仍然可以正常工作。它是一个程序,用于绘制一组ping响应的平均时间,以查看当天是否存在任何模式。来源如下

from Tkinter import *
import matplotlib
import time
import os, sys, threading, Queue
matplotlib.use('TkAgg')
from numpy import arange, array, sin, pi
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure

import Tkinter
import sys
class App(object):
    def __init__(self):
        self.q = Queue.Queue()
        self.q2 = Queue.Queue()
        self.avvals=[]
        self.addlist=['bbc.co.uk', 'google.co.uk', 'nhgs.co.uk', 'bing.co.uk', 'msn.com']
        self.addlistlen = len(self.addlist)
        self.root = Tkinter.Tk()
        self.root.wm_title("Connection Speed")
        self.frame = Tkinter.Frame(self.root)
        self.frame.pack(side='top', expand=1, fill='both',)
        self.frame2 = Tkinter.Frame(self.frame)
        self.frame2.pack(side='bottom', expand=1, fill='both',)
        self.f = Figure(figsize=(5,4), dpi=100)
        self.a = self.f.add_subplot(111)
        self.gframe = Tkinter.Frame(self.frame)
        self.gframe.pack(side='top', expand=1, fill='both',)
        self.canvas = FigureCanvasTkAgg(self.f, master=self.gframe)
        self.canvas.show()
        self.canvas.get_tk_widget().pack(side='top', fill='both', expand=1)
        self.canvas._tkcanvas.pack(side='top', fill='both', expand=1)
        self.lt = threading.Thread(target=self.loop())
    def getping(self, add):
            pingaling = os.popen("ping -n 2 "+str(add).strip())
            sys.stdout.flush()
            line = pingaling.read()
            if line:
                try:
                    line = line.split('Maximum = ')[1]
                    time = line.split('ms, Average')[0]
                    self.q.put(int(time))
                except:
                    self.q.put(None)
    def gpthread(self, *a):
        t = threading.Thread(target=self.getping, args=a)
        t.isDaemon = True
        t.start()
    def loop(self):
        while 1:
            for x in self.addlist:
                self.gpthread(x)
            while self.q.qsize<self.addlistlen:
                pass
            tl = []
            for u in range(self.addlistlen):
                temp = self.q.get()
                if temp != None:
                    tl.append(temp)
            if len(tl)>0:
                self.update(sum(tl)/len(tl))
            else:
                self.update(None)
    def update(self, val):
        self.a.clear()
        self.avvals.append(val)
        self.a.plot(self.avvals, linewidth=0.5, color = 'b')
        self.canvas.draw()
a = App()
try:
    a.root.mainloop()
except:
    a.root.destroy()

我可能不需要底部试试..除了我把它放入检查它是否会有所作为。 我没有机会在另一台计算机上试用它,但我的其他脚本工作得很好...... 我根本无法理解为什么它冻结,停止响应,如果我通过任何方法退出它我得到一个错误说 致命的python错误:PyEval NULL tstate 或者非常相似的东西。 现在它甚至没有扩大!它只是直接没有回应!

1 个答案:

答案 0 :(得分:6)

更改

self.lt = threading.Thread(target=self.loop())

self.lt = threading.Thread(target=self.loop)

target=self.loop()在将结果传递给loop之前调用threading.Thread方法

传递target=self.loop将方法对象传递给threading.Thread而不调用它。这允许threading.Thread在新线程中调用该方法。


以下是一些使用线程ping某些ips的代码,并在嵌入Tkinter窗口的动画matplotlib条形图中显示平均ping时间:

import Tkinter
import threading
import subprocess
import Queue
import shlex
import re
import matplotlib.pyplot as plt
import matplotlib.backends.backend_tkagg as tkagg
import atexit
import numpy as np

pingers=[]
def cleanup():
    print('terminating ping subprocesses...')
    for pinger in pingers:
        pinger.proc.terminate()        
atexit.register(cleanup)

class Pinger(threading.Thread):
    def __init__(self,app,queue):
        threading.Thread.__init__(self)        
        self.app=app
        self.queue=queue
    def run(self):
        # One ping subprocess is started by each Pinger thread.
        # The ping subprocess runs indefinitely, terminated by the cleanup function
        # which is called by atexit right before the main program terminates.
        ip = self.queue.get()
        cmd="ping %s" % ip
        self.proc = subprocess.Popen(shlex.split(cmd),
                                     stdout=subprocess.PIPE)
        for line in iter(self.proc.stdout.readline,''):
            match=re.search('time=(.*)\s+ms',line)
            if match:
                avg=float(match.group(1))
                self.app.update(ip,avg)

class App(object):
    def __init__(self,master,ips):
        self.ips=ips
        self.fig = plt.Figure(figsize=(5,4), dpi=100)
        self.fig.subplots_adjust(bottom=0.25) 
        self.ax=self.fig.add_subplot(1,1,1)
        self.canvas = tkagg.FigureCanvasTkAgg(self.fig, master=master)
        self.canvas.get_tk_widget().pack(side='top', fill='both', expand=1)
        self.canvas.show()
        N=len(self.ips)
        self.idx=dict(zip(self.ips,range(N)))
        # I set an initial ping time of 200 just to make the initial bar chart
        times=[200]*N  
        self.rects=self.ax.bar(range(N), times)
        self.ax.set_xticks(np.arange(N)+0.8*0.5)
        self.ax.set_xticklabels(self.ips, rotation=25)
    def update(self,ip,avg):
        # This is called by Pinger threads, each time a new ping value is obtained
        print(ip,avg)
        self.rects[self.idx[ip]].set_height(avg)
        self.canvas.draw()

def main():    
    root = Tkinter.Tk()
    root.wm_title("Connection Speed")
    ips=['bbc.co.uk', 'google.co.uk', 'nhgs.co.uk', 'bing.co.uk', 'msn.com']
    app = App(root,ips)
    queue = Queue.Queue()
    for ip in ips:
        queue.put(ip)
        # This starts one Pinger for each ip.
        pinger=Pinger(app,queue)
        pingers.append(pinger)
        pinger.daemon=True
        pinger.start()
    Tkinter.mainloop()

if __name__=='__main__':
    main()