如何在一个Python脚本中控制/调用另一个Python脚本?(脚本之间进行通信)

Sha*_*ane 3 python wxpython event-handling

我正在开发一个 GUI 程序,并且打算将一个长时间运行的任务添加到一个事件中,但我发现这会使整个程序冻结很多,所以考虑到其他人的建议,我会让 GUI 只负责启动、停止监视并使长时间运行的任务作为单独的脚本运行。我知道在一个脚本中运行另一个脚本的唯一方法是通过导入,是否有其他方法与另一个脚本进行通信,我的意思是读取另一个脚本的标准输出并在您想要的任何时候终止它?

vol*_*ing 5

我建议你看看线程模块。通过Thread子类化该类,您可以为时间密集型作业创建新线程。

然后,对于线程之间的通信,您可以使用pubsubpydispatcher,我还没有尝试过后者,所以我无法对其发表评论,但我会推荐 pubsub 因为它易于使用,而且它与 wxpython 的区别是奖金。

是一个关于运行长任务的 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()
Run Code Online (Sandbox Code Playgroud)