我正在开发一个GUI程序,并且会在一个事件中添加一个长时间运行的任务,但我发现这会使整个程序冻结很多,所以考虑到其他人的建议我会让GUI只负责启动,停止和监视并使长时间运行的任务作为单独的脚本运行。我知道在一个脚本中运行另一个脚本的唯一方法是导入,有没有其他方法与另一个脚本进行通信,我的意思是读取另一个stdout并在任何时候终止它?
答案 0 :(得分:4)
我建议您查看threading module。通过子类化Thread
类,您可以为时间密集型作业创建新线程。
然后,对于线程之间的通信,您可以使用pubsub或pydispatcher,我没有尝试后者,所以我不能评论它,但我会推荐pubsub,因为它的易用性使用和wxpython的区别是奖金。
Here 是关于运行长任务的wxpython wiki页面,如果你想要最简单的线程示例用法,请跳到最后。
下面是一个简单(可运行)示例,说明如何使用pubsub
将来自workerThread的邮件发送到GUI
。
import time
import wx
from threading import Thread
from wx.lib.pubsub import Publisher
class WorkerThread(Thread):
def __init__(self):
Thread.__init__(self)
#A flag that can be set
#to tell the thread to end
self.stop_flag = False
#This calls the run() to start the new thread
self.start()
def run(self):
""" Over-rides the super-classes run()"""
#Put everything in here that
#you want to run in your new thread
#e.g...
for x in range(20):
if self.stop_flag:
break
time.sleep(1)
#Broadcast a message to who ever's listening
Publisher.sendMessage("your_topic_name", x)
Publisher.sendMessage("your_topic_name", "finished")
def stop(self):
"""
Call this method to tell the thread to stop
"""
self.stop_flag = True
class GUI(wx.Frame):
def __init__(self, parent, id=-1,title=""):
wx.Frame.__init__(self, parent, id, title, size=(140,180))
self.SetMinSize((140,180))
panel = wx.Panel(id=wx.ID_ANY, name=u'mainPanel', parent=self)
#Subscribe to messages from the workerThread
Publisher().subscribe(self.your_message_handler, "your_topic_name")
#A button to start the workerThread
self.startButton = wx.Button(panel, wx.ID_ANY, 'Start thread')
self.Bind(wx.EVT_BUTTON, self.onStart, self.startButton)
#A button to stop the workerThread
self.stopButton = wx.Button(panel, wx.ID_ANY, 'Stop thread')
self.Bind(wx.EVT_BUTTON, self.onStop, self.stopButton)
#A text control to display messages from the worker thread
self.threadMessage = wx.TextCtrl(panel, wx.ID_ANY, '', size=(75, 20))
#Do the layout
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.startButton, 0, wx.ALL, 10)
sizer.Add(self.stopButton, 0, wx.ALL, 10)
sizer.Add(self.threadMessage, 0, wx.ALL, 10)
panel.SetSizerAndFit(sizer)
def onStart(self, event):
#Start the worker thread
self.worker = WorkerThread()
#Disable any widgets which could affect your thread
self.startButton.Disable()
def onStop(self, message):
self.worker.stop()
def your_message_handler(self, message):
message_data = message.data
if message_data == 'finished':
self.startButton.Enable()
self.threadMessage.SetLabel(str(message_data))
else:
self.threadMessage.SetLabel(str(message_data))
if __name__ == "__main__":
app = wx.PySimpleApp()
frame = GUI(None, wx.ID_ANY, 'Threading Example')
frame.Show()
app.MainLoop()
答案 1 :(得分:1)
如果你需要通过stdin / stdout进行通信,你应该使用subprocess
模块。
答案 2 :(得分:1)
除了阅读标准输出:http://docs.python.org/library/multiprocessing.html
之外,还有更好的方法