如何在一个python脚本中控制/调用另一个python脚本? (脚本之间的沟通) [英] How to control/call another python script within one python script? (Communicate between scripts)

查看:1055
本文介绍了如何在一个python脚本中控制/调用另一个python脚本? (脚本之间的沟通)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

解决方案

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



然后,线程之间的通信可以使用 pubsub pydispatcher ,我没有尝试过后者,所以我不能评论它,但我会推荐pubsub的易用性,以及它的wxpython的分配是一个奖金。



这里是一个关于运行长任务的wxpython维基页面,如果您想要最简单的线程使用示例,请跳过到最后。






是一个简单(可运行)的例子,说明如何使用 pubsub 将消息从您的workerThread发送到您的 GUI

  import时间

导入wx
从线程导入线程
从wx.lib.pubsub import Publisher

class WorkerThread(Thread):
def __init __(self):
Thread .__ init __(self)

#A可以设置的标志
#告诉线程结束
self.stop_flag = False

#这个调用run()来启动新线程
self.start()


def run(self):
超级跑跑()
#在这里的所有东西
#你想在你的新线程中运行

#eg ..
for x in range(20):
if self.stop_flag:
break
time.sleep(1)
#Broadcast一条消息给谁收听
Publisher.sendMessage(your_topic_name,x)
Publisher.sendMessage(your_topic_name,finished)


def stop(self )

调用此方法告诉线程停止

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 )

#订阅来自workerThread的消息
Publisher()。subscribe(self.your_message_handler,your_topic_name)

#A按钮启动workerThread
self.startButton = wx.Button(panel,wx.ID_ANY,'Start thread')
self.Bind(wx.EVT_BUTTON,self.onStart,self.startButton)

#A按钮停止工作线程
self.stopButton = wx.Button(panel,wx.ID_ANY,'Stop thread')
self.Bind(wx.EVT_BUTTON,self.onStop,self.stopButton)

#A文本控件显示来自工作线程的消息
self.threadMessage = wx.TextCtrl(panel,wx.ID_ANY,'',size =(75,20))

#Do布局
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):
#启动工作线程
self.worker = WorkerThread()

#Disable任何可能影响你的线程的小部件
self.startButton.Disable()

def onStop(self,message):
self.worker.stop()

def your_message_handler(self,message):
message_data = message.data
如果message_data =='finished':
self.startButton.Enable()
self.threadMessage.SetLabel(str(message_data))
else:
self.threadMessage.SetLabel(str(message_data))

如果__name__ ==__main__:

app = wx.PySimpleApp()
框架= GUI(无,wx.ID_ANY,'线程示例')
frame.Show()
app.MainLoop()


I'm working on one GUI program, and was gonna add a long running task into one event, but I found this would make the whole program freeze a lot, so considering other people's advice I would make the GUI only responsible for starting, stopping and monitoring and make the long running task run as a separate script. The only way I know to run another script in one script is by import, is there any other methods to communicate with another script, I mean such as reading another's stdout and terminating it at any time you want?

解决方案

I suggest you look at the threading module. By subclassing the Thread class you can create new threads for time intensive jobs.

Then for communication between the the threads you can use either pubsub or pydispatcher, I haven't tried the latter so I can't comment on it but I would recommend pubsub for its ease of use and the fact that its apart of wxpython is a bonus.

Here is a wxpython wiki page on running long tasks, skip to the end if you want the simplest example usage of threading.


Heres a simple (runnable) example of how you could use pubsub to send messages from your workerThread to your 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()

这篇关于如何在一个python脚本中控制/调用另一个python脚本? (脚本之间的沟通)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆