2015-09-19 23 views
0

我正在用Python写一个简单的程序。我希望类RequestHandler和GUI类同时在单独的线程中运行,并且已经在RequestHandler中生成的消息(经常在GUI中显示(在每个post请求中将生成一条或两条消息))中显示。这里遵循我的代码的简化版本:带GUI GUI的ThreadedHTTPServer不是在python中写的

import web 
import io,json 
from SocketServer import ThreadingMixIn 
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler 
urls = ('/', 'RequestHandler') 

from time import sleep 
import threading 
from Tkinter import * 

serialdata = [] 
data = True 
msguser = '' 

class RequestHandler(BaseHTTPRequestHandler): 
    def do_POST(self): 
     length = int(self.headers['Content-length']) 
     mylogs=self.rfile.readline(length) 
     val= json.loads(mylogs) 
     if val['RunningApp'].find('viber') >= 0:   
      msguser = 'viber is running on Devise ID:',val['DeviceID'],'in time:',val['timestamp'] 
      serialdata.append(msguser) 
     if val['RunningApp'].find('telegram.messenger') >= 0: 
      msguser = 'Telegram is running on Devise ID:',val['DeviceID'],'in time:',val['timestamp'] 
      serialdata.append(msguser) 

class ThreadedHTTPServer(ThreadingMixIn, HTTPServer): 
    pass 

class Gui(object): 
    def __init__(self): 
     self.root = Tk() 
     self.lbl = Label(self.root, text="") 
     self.updateGUI() 
     self.readSensor() 

    def run(self): 
     self.lbl.pack() 
     self.lbl.after(1000, self.updateGUI) 
     self.root.mainloop() 

    def updateGUI(self): 
     msg = "Data is True" if data else "Data is False" 
     self.lbl["text"] = msg 
     self.root.update() 
     self.lbl.after(1000, self.updateGUI) 

    def readSensor(self): 
     self.lbl["text"] = serialdata[-1] 
     self.root.update() 
     self.root.after(527, self.readSensor) 

if __name__ == "__main__": 
    server = ThreadedHTTPServer(('X.X.X.X', 1024), RequestHandler) 
    print 'Starting server, use <Ctrl-C> to stop' 
    Gui().run() 
    server.serve_forever() 

当我运行它,我得到错误:self.lbl["text"] = serialdata[-1] IndexError: list index out of range 还当我给了self.lbl["text"]像一个静态字符串“新事件收到”

程序不像多线程一样工作,直到GUI运行,从不运行和工作。

+0

可否请你的代码剥离下来到最低工作实例?缺少导入(例如Tk,ThreadingMixIn),您正在使用未定义的变量(例如数据和串行数据)等。您不帮助我们帮助您!对于你的具体错误,第一个可能意味着'serialdata'是空的(即'len(serialdata)== 0')。第二个可能是因为'Gui()。run()'是一个阻塞调用(它不返回),所以你的代码永远不会调用'server.serve_forever()'。您应该查看['multiprocessing'模块](https://docs.python.org/2/library/multiprocessing.html) – jorgeh

+0

抱歉,出现错误,我现在编辑我的代码,请告诉我该怎么做更改我的代码以解决我的问题并正确运行。 – sonia

回答

0

你必须在它自己的线程中运行服务器:

def main(): 
    server = ThreadedHTTPServer(('X.X.X.X', 1024), RequestHandler) 
    print 'Starting server, use <Ctrl-C> to stop' 
    server_thread = threading.Thread(target=server.serve_forever) 
    server_thread.start() 
    Gui().run() 
    server.shutdown() 

if __name__ == "__main__": 
    main() 

一开始serialdata是空的,所以访问serialdata[-1]失败。因此,检查,数据是否可用:

def readSensor(self): 
    if serialdata: 
     self.lbl["text"] = serialdata.pop() 
    self.root.after(527, self.readSensor) 

仍然较好,使用队列通信:

import threading 
import json 
from Queue import Queue, Empty 
from SocketServer import ThreadingMixIn 
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler 
import Tkinter as tk 

class RequestHandler(BaseHTTPRequestHandler): 
    def do_POST(self): 
     length = int(self.headers['Content-length']) 
     mylogs = self.rfile.read(length) 
     val = json.loads(mylogs) 
     if 'viber' in val['RunningApp']: 
      app = 'viber' 
     if 'telegram.messenger' in val['RunningApp']: 
      app = 'Telegram' 
     self.server.queue.put('%s is running on Devise ID: %s in time: %s' % (app, val['DeviceID'], val['timestamp'])) 

class ThreadedHTTPServer(ThreadingMixIn, HTTPServer): 
    pass 

class Gui(object): 
    def __init__(self, root, queue): 
     self.queue = queue 
     self.lbl = tk.Label(root, text="") 
     self.lbl.pack() 
     self.read_sensor() 

    def read_sensor(self): 
     try: 
      self.lbl["text"] = self.queue.get_nowait() 
     except Empty: 
      pass 
     self.lbl.after(527, self.readSensor) 

def main(): 
    server = ThreadedHTTPServer(('X.X.X.X', 1024), RequestHandler) 
    server.queue = Queue() 
    print 'Starting server, use <Ctrl-C> to stop' 
    server_thread = threading.Thread(target=server.serve_forever) 
    server_thread.start() 
    root = tk.Tk() 
    gui = Gui(root, server.queue) 
    root.mainloop() 
    server.shutdown() 

if __name__ == "__main__": 
    main() 
+0

太棒了!非常感谢你,你的回答很明确和有帮助!其中一个问题现在正在解决,多线程正在工作,但其他问题仍然存在,错误:'IndexError:列表索引超出范围'我可以猜出为什么会发生,但我不知道要修复它 – sonia

+0

坦克你非常非常丹尼尔。它工作正常!让我知道一件事。放入衣服不能在代码中一次。字符串替换在一起,这是错误的。 – sonia