Python asyncio等待线程

时间:2016-05-14 07:20:45

标签: python asynchronous async-await python-multithreading

我的情况是我有一台服务器"应该监听来自其他服务器线程的调用/事件,同时执行其他一些代码的线程。最近我在Node.js上做了很多工作,所以我认为使用async / await创建一个事件循环会很好,我可以等待其他线程加入事件循环并在最终加入时处理它们的响应。

为了测试这个想法,我在Python 3.5中编写了以下测试脚本:

# http://stackabuse.com/python-async-await-tutorial/
# Testing out Python's asynchronous features
import asyncio
from time import sleep
import threading
from threading import Thread
import random

class MyThread(Thread):

    def __init__(self, message):
        Thread.__init__(self)
        self._message = message

    def run(self):
        self._return = self._message + " oli viesti"
        a = random.randint(1, 5)
        print("Sleep for ", a)
        sleep(a)
        print("Thread exiting...")


    def join(self):
        Thread.join(self)
        return self._return



async def send(message):
    t = MyThread(message)  # daemon = True
    t.start()
    print("asd")
    return t.join()

async def sendmsg(msg):
    response = await send(msg)
    print("response is ", response)


if __name__ == "__main__":
    # Initiate a new thread and pass in keyword argument dictionary as parameters
    loop = asyncio.get_event_loop()
    tasks = [
        asyncio.ensure_future(sendmsg("hippa1"), loop=loop),
        asyncio.ensure_future(sendmsg("hippa2"), loop=loop),
        asyncio.ensure_future(sendmsg("hippa3"), loop=loop)
    ]

    loop.run_until_complete(asyncio.wait(tasks))
    loop.close()

在示例中,我想要使用不同的字符串启动三个工作线程并等待它们完成。工作人员随机睡眠时间,所以我希望它们在脚本多次运行时以随机顺序完成。事实证明,他们似乎顺序执行,第二个线程首先启动。

我的错误是什么?难道不应该只阻止它所在的线程吗?我的事件循环是否设置正确?我可以异步/等待加入吗?

最终我想将消息发送到其他线程并等待其响应,然后运行带有返回值的回调函数。

编辑:为了澄清,最终我想在主线程中等待带有async / await的条件变量并运行其他代码,直到某些条件变量允许执行。在这个示例代码中,我试图对工作线程的连接做同样的事情。

1 个答案:

答案 0 :(得分:0)

最终,由于此代码,它按顺序运行:

async def send(message):
    t = MyThread(message)  # daemon = True
    t.start()
    print("asd")
    return t.join()

启动一个线程,然后在继续之前立即等待该线程完成。这就是他们按顺序执行的原因。

Node.js和asyncio不一定会创建新线程来执行其操作。例如,Node.js只使用单个线程,但它使用内核级功能(例如,#ep;')来调用您在发生新网络活动时指示的回调。这允许单个线程管理数百个网络连接。

这就是为什么当你在没有Thread实例的情况下执行它时,你可以在当前运行的线程上调用sleep,这与主线程相同。当您将asyncio与网络功能一起使用时,您可以使用" yield from"结构,允许其他代码块执行,而其他任务正在与其他远程服务一起执行。

主要结构是正确的。你想要这段代码:

loop.run_until_complete(asyncio.wait(tasks))

但不要依赖“睡眠”。要测试该功能,您需要进行网络呼叫,或使用:

yield from asyncio.sleep(1)

在这种情况下,没有必要开始单独的线程。