如何通过异步方法/线程传递/交换数据?

时间:2019-01-09 00:14:30

标签: python multithreading python-2.7 asynchronous

有人可以解释一下如何在python中的异步调用之间传递数据吗?

我有这种情况:
我有一个主过程(mainthread),然后运行另一个异步调用,该调用将两个numbers()相加并休眠一段时间。期望让主线程等到calc和sleeping完成。就伪代码而言,这可能像这样:

def example():
    def my_calc(x,y):
        z = x+ y
        time.sleep(2)
        return z  #this should get pushed to queue, but for simplicity we use 'return z'

    z = asyncSomething.callInThread(my_calc, 2, 20)  #assume we get z from queue
    return z+10

def runner():  #our main function
    print 'start'
    z = example()
    print 'result is {0}'.format(z)

如何让最后一个print等待z?我尝试使用threading.Event()并与setwaitclear一起玩,但是它们阻塞了所有内容。

我认为我的案子不是唯一的,必须有一种整齐的系统方式来处理。我看着扭曲的反应堆,但部分成功。我的实际代码涉及GUI,必须等待异步过程的结果,然后进行自我更新和自动更新...但是我认为该示例描述了大部分问题

我认为我缺少有关如何在python中异步工作的实际概念。

2 个答案:

答案 0 :(得分:1)

如果使用多线程,则应使用futures封装结果。具体来说,future.result(timeout=None)将用于您的情况:

  

返回调用返回的值。如果通话尚未完成,则此方法将等待超时秒数。如果通话未在超时秒内完成,则将引发并发.futures.TimeoutError。超时可以是int或float。如果未指定超时或“无”,则等待时间没有限制。

如上面的注释中所述,如果您不使用多线程(并且使用异步编程),那么回调将是可行的方法。

答案 1 :(得分:1)

如果您的主线程在没有工作线程结果的情况下进行了有意义的扩展,并且您想阻塞,则可以使用threading.Event等待工作线程执行中的某个点,或者thread.join(其中threadthreading.Thread实例)等待工作线程完成:

class Example(object):
    def my_calc(self, x, y):
        time.sleep(2)
        self._z = x + y # or push the result to a queue

    def example(self):
        thread = threading.Thread(target=self.my_calc, args=(2, 20))
        thread.start()
        # any other useful work could go here while the worker runs
        thread.join()
        return self._z + 10 # or grab the result from a queue

def runner():
    print "start"
    z = Example().example()
    print "result is {0}".format(z)

但是,在GUI的上下文中,您的主线程不太可能取得最大进展-它可能一直在忙于保持GUI的响应速度。在那种情况下,正如对该问题的评论中提到的那样,最好将工作人员的计算完成之后想要打包的所有内容打包到工作线程要调用的回调中:

def my_calc(x, y):
    time.sleep(2)
    return x + y

def my_calc_thread(x, y, callback):
    z = my_calc(x, y)
    # depending on your GUI framework, you may need to do something
    # like call_in_main_thread(callback, z) if callback touches GUI
    # elements
    callback(z)

def example():
    def finish(z):
        print "result is {0}".format(z)
    t = threading.Thread(target=my_calc_thread, args=(2, 20, finish))
    t.start()

def runner():
    print "start"
    example()