Python 脚本无缘无故冻结(据我所知)

发布于 2024-10-11 09:43:58 字数 2932 浏览 1 评论 0原文

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

i'm not particularly new at python but i just thought there might be a reason for this program not working properly. i have written a similar one from which this is derived, and that still works fine. it is a program to graph the average time of a set of ping responses, to see if there is any pattern in the time over the day. the source is as follows

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

i probably dont need the bottom try..except but i put it in to check if it would make a difference.
i haven't had a chance to try it on another computer, but my other scripts are working fine so....
i simply can't comprehend why it freezes, stops responding, and if i exit it by any method i get a error saying
Fatal python error: PyEval NULL tstate
or somthing very similar.
now it doesn't even expand! it just goes straight to not responding!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

慕烟庭风 2024-10-18 09:43:58

更改

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,并在嵌入 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()

Change

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

to

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

target=self.loop() calls the loop method before passing the result to threading.Thread.

Passing target=self.loop passes the method object to threading.Thread without calling it. This lets threading.Thread call the method in a new thread.


Here is some code which uses threads to ping some ips, and displays the average ping times in an animated matplotlib bar chart, embedded in a Tkinter window:

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文