简体   繁体   English

Python asyncio 等待线程

[英]Python asyncio wait for threads

I have a situation where I have a "server" thread which should listen calls/events from other server threads while at the same time executing some other code.我有一种情况,我有一个“服务器”线程,它应该侦听来自其他服务器线程的调用/事件,同时执行其他一些代码。 Lately I have worked a lot with Node.js so I thought that it would be nice to use async/await to create an event loop where I can wait other threads to join in event loop and handle their response when they finally join.最近我在 Node.js 上做了很多工作,所以我认为使用 async/await 创建一个事件循环会很好,我可以在其中等待其他线程加入事件循环并在它们最终加入时处理它们的响应。

To test the idea I wrote the following test script in Python 3.5:为了测试这个想法,我在 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()

In the example I want to kick off three worker threads with different strings and wait for them to finish.在这个例子中,我想用不同的字符串启动三个工作线程并等待它们完成。 Workers sleep random amount of time so I expect them to finish in random order when script is run multiple times.工人的睡眠时间是随机的,所以我希望他们在多次运行脚本时以随机顺序完成。 Turns out that they seem to execute sequentially instead, second thread starting after first.事实证明,它们似乎是按顺序执行的,第二个线程在第一个线程之后开始。

What is my error here?我的错误是什么? Shouldn't sleep block only the thread it is in? sleep 不应该只阻塞它所在的线程吗? Is my event loop set up correctly?我的事件循环设置正确吗? Can I async/await joins?我可以异步/等待加入吗?

Ultimately I want to send messages to other threads and wait for their response to then run a callback function with returned value.最终我想向其他线程发送消息并等待他们的响应然后运行带有返回值的回调函数。

EDIT: To clarify, ultimately I want to wait for conditional variables with async/await in my main thread and run other code until some of the conditional variables let execution through.编辑:为了澄清,最终我想在我的主线程中等待带有 async/await 的条件变量并运行其他代码,直到某些条件变量让执行通过。 In this example code I was trying to do the same with worker thread's join.在这个示例代码中,我试图对工作线程的连接做同样的事情。

Ultimately, it is running sequentially because of this code:最终,由于以下代码,它按顺序运行:

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

You start a thread, then immediately wait on that thread to finish before you continue.您启动一个线程,然后立即等待该线程完成,然后再继续。 This is why they're executed sequentially.这就是它们顺序执行的原因。

Node.js and asyncio do not necessarily create new threads to execute their operations. Node.js 和 asyncio 不一定会创建新线程来执行它们的操作。 Node.js for example only ever uses a single thread, but it uses kernel level functions ( for example 'epoll' ) to call the callbacks that you indicate when some new network activity occurred.例如,Node.js 只使用单个线程,但它使用内核级函数(例如 'epoll' )来调用您指示何时发生某些新网络活动的回调。 This allows a single thread to manage hundreds of network connections.这允许单个线程管理数百个网络连接。

That's why probably when you executed this without the Thread instance, you'd call sleep on the currently running thread, which is the same as the main thread.这就是为什么当您在没有 Thread 实例的情况下执行此操作时,您可能会在当前运行的线程上调用 sleep,这与主线程相同。 When you use asyncio with networking functions, then you can use "yield from" structures, which allows other code blocks to execute while the other tasks are doing things with other remote services.当您将 asyncio 与网络功能一起使用时,您可以使用“yield from”结构,它允许其他代码块在其他任务与其他远程服务一起执行时执行。

The main structure is correct.主要结构是正确的。 You want this block of code:你想要这个代码块:

loop.run_until_complete(asyncio.wait(tasks))

But don't rely on 'sleep' to test the function, you need to make a networking call, or use:但是不要依赖'sleep'来测试功能,需要进行网络调用,或者使用:

yield from asyncio.sleep(1)

And there's no need to start separate threads in that case.在这种情况下不需要启动单独的线程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM