我正在用Python编写一个简单的程序。我希望RequestHandler
的类和GUI类同时在单独的线程中运行,并且在RequestHandler中生成的消息经常在GUI中显示(在每个post请求中将生成一个或两个消息)。这是我的代码的简化版本:
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运行之前do_post
永远不会运行和工作。
答案 0 :(得分: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()