Skip to main content
 首页 » 编程设计

Python 脚本无缘无故卡住 (afaik)

2025年05月04日17cyq1162

我对 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 或者非常相似的东西。 现在它甚至没有扩大!它只是直接没有响应!

请您参考如下方法:

改变

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

到

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

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

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


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

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()