Python:如何让程序等到函数或方法完成 [英] Python: How to make program wait till function's or method's completion

查看:45
本文介绍了Python:如何让程序等到函数或方法完成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

程序经常需要等待一个函数完成它的工作.有时恰恰相反:主程序不需要等待.我举了一个简单的例子.有四个按钮.单击每个将调用相同的 calculate() 函数.唯一的区别是函数的调用方式.

Often there is a need for the program to wait for a function to complete its work. Sometimes it is opposite: there is no need for a main program to wait. I've put a simple example. There are four buttons. Clicking each will call the same calculate() function. The only difference is the way the function is called.

  1. 直接调用" 按钮直接调用calculate() 函数.由于有函数结束"打印输出,很明显程序正在等待计算函数完成其工作.
  2. 通过线程调用" 这次使用线程机制调用相同的函数.由于程序在按下按钮后立即打印出 ':Function End' 消息,我可以得出结论,该程序不会等待 calculate() 函数完成.如何覆盖此行为?如何让程序等待到calculate()函数完成?
  3. 通过多处理调用" 按钮利用多处理调用calculate() 函数.就像线程多处理不等待函数完成一样.为了让它等待,我们必须发表什么声明?

  1. "Call Directly" button calls calculate() function directly. Since there is a 'Function End' print out it is evident that the program is waiting for the calculate function to complete its job.
  2. "Call via Threading" calls the same function this time using threading mechanism. Since the program prints out ': Function End' message immidiately after the button is presses I can conclude the program doesn't wait for calculate() function to complete. How to override this behavior? How to make program wait till calculate() function is finished?
  3. "Call via Multiprocessing" buttons utilizes multiprocessing to call calculate() function. Just like with threading multiprocessing doesn't wait for function completion. What statement we have to put in order to make it wait?

通过子进程调用" 按钮没有做任何事情,因为我没有找到挂钩子进程以运行内部脚本函数或方法的方法.看看怎么做会很有趣...

"Call via Subprocess" buttons doesn't do anything since I didn't figure out the way to hook subprocess to run internal script function or method. It would be interesting to see how to do it...

示例:

from PyQt4 import QtCore, QtGui    
app = QtGui.QApplication(sys.argv)


def calculate(listArg=None):
    print '\n\t Starting calculation...'
    m=0
    for i in range(50000000):
        m+=i
    print '\t ...calculation completed\n'


class Dialog_01(QtGui.QMainWindow):
    def __init__(self):
        super(Dialog_01, self).__init__()

        myQWidget = QtGui.QWidget()
        myBoxLayout = QtGui.QVBoxLayout()       

        directCall_button = QtGui.QPushButton("Call Directly")
        directCall_button.clicked.connect(self.callDirectly)      
        myBoxLayout.addWidget(directCall_button) 

        Button_01 = QtGui.QPushButton("Call via Threading")
        Button_01.clicked.connect(self.callUsingThreads)
        myBoxLayout.addWidget(Button_01)        

        Button_02 = QtGui.QPushButton("Call via Multiprocessing")
        Button_02.clicked.connect(self.callUsingMultiprocessing)
        myBoxLayout.addWidget(Button_02) 

        Button_03 = QtGui.QPushButton("Call via Subprocess")
        Button_03.clicked.connect(self.callUsingSubprocess)
        myBoxLayout.addWidget(Button_03) 


        myQWidget.setLayout(myBoxLayout)
        self.setCentralWidget(myQWidget)
        self.setWindowTitle('Dialog 01')

    def callUsingThreads(self):
        print '------------------------------- callUsingThreads() ----------------------------------'
        import threading
        self.myEvent=threading.Event()
        self.c_thread=threading.Thread(target=calculate)
        self.c_thread.start()  

        print "\n\t\t : Function End"


    def callUsingMultiprocessing(self):
        print '------------------------------- callUsingMultiprocessing() ----------------------------------'
        from multiprocessing import Pool

        pool = Pool(processes=3)
        try: pool.map_async( calculate, ['some'])
        except Exception, e: print e 

        print "\n\t\t : Function End"


    def callDirectly(self):
        print '------------------------------- callDirectly() ----------------------------------'
        calculate()
        print "\n\t\t : Function End"


    def callUsingSubprocess(self):
        print '------------------------------- callUsingSubprocess() ----------------------------------'
        import subprocess 
        print '-missing code solution'
        print "\n\t\t : Function End"


if __name__ == '__main__':
    dialog_1 = Dialog_01()
    dialog_1.show()
    dialog_1.resize(480,320)
    sys.exit(app.exec_())

推荐答案

使用队列:每个线程在完成时将结果放入队列,然后您只需要读取适当数量的结果并忽略余数:

Use a queue: each thread when completed puts the result on the queue and then you just need to read the appropriate number of results and ignore the remainder:

#!python3.3
import queue    # For Python 2.x use 'import Queue as queue'
import threading, time, random

def func(id, result_queue):
    print("Thread", id)
    time.sleep(random.random() * 5)
    result_queue.put((id, 'done'))

def main():
    q = queue.Queue()
    threads = [ threading.Thread(target=func, args=(i, q)) for i in range(5) ]
    for th in threads:
        th.daemon = True
        th.start()

    result1 = q.get()
    result2 = q.get()

    print("Second result: {}".format(result2))

if __name__=='__main__':
    main()

Queue.get() 的文档(没有参数,它等价于 Queue.get(True, None):

Documentation for Queue.get() (with no arguments it is equivalent to Queue.get(True, None):

    Queue.get([block[, timeout]])

Remove and return an item from the queue. If optional args block is true and timeout is None (the default), block if necessary until an item is available. If timeout is a positive number, it blocks at most timeout seconds and raises the Empty exception if no item was available within that time. Otherwise (block is false), return an item if one is immediately available, else raise the Empty exception (timeout is ignored in that case).

如何等到只有第一个线程在 Python 中完成

您也可以使用 .join() 方法.python线程中join()的作用是什么

You can to use .join() method too. what is the use of join() in python threading

这篇关于Python:如何让程序等到函数或方法完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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