python – 如何组合两个异步库?

我如何在同一个程序中组合两个asyncio库?

对于上下文,我希望将Discord api与aiohttp一起使用,两者都是异步事件循环驱动的.我可能也想在混合中添加异步irc库.

但是,我不明白它们将如何一起运作.我相信在理论上我会实现程序,使所有类实例使用相同的asyncio事件循环实例,然后将所有运行函数合并为一个,最终调用事件循环.

但是,我想知道一般来说是否有一种更优雅的方式呢?

最佳答案 只要所有库都使用相同的eventloop,它们就可以很好地协同工作.在这种情况下,您选择的所有库似乎都基于asyncio(除了gawel的IRC lib之外不再可用).所以没有问题.有一个eventloop(没有线程),一切都很好.

您面临的问题是,您将在同一个事件循环中拥有多个“服务器”,或者更准确地说,有几个协程可以处理来自外部世界的输入.一个协同程序正在处理HTTP流量,另一个正在处理IRC“流量”.在伪代码中,它可以转换为以下内容:

import asyncio


@asyncio.coroutine
async def irc_server():
    async with irc_connect('irc.freenode.net#python-fr') as irc:
        async for message in irc:
            # do something useful with message

@asyncio.coroutine
async def web_server():
    async with web_connect('localhost:8080') as web:
        async for request in web:
            # do something useful with request


loop = asyncio.get_event_loop()
loop.create_task(irc_server())
loop.create_task(irc_server())

loop.run_forever()

因此,两个协同程序都无法进行通信.要使HTTP部分与IRC部分通信,您必须在两个协同程序之间共享内容.在生产中它是数据库的一部分,但在伪代码中,它是一个简单的全局.你会得到类似的东西:

import asyncio


# value is shared between IRC and the web server.
value = None


@asyncio.coroutine
async def irc_server():
    global value
    async with irc_connect('irc.freenode.net#python-fr') as irc:
        async for message in irc:
            # if message is echo, reply with the current value
            # otherwise store the message as value
            if message == 'echo':
                irc.send(value)
            else:
                value = message

@asyncio.coroutine
async def web_server():
    global value
    async with web_connect('localhost:8080') as web:
        async for request in web:
            if request.path == 'echo':
                request.client.send(value)
            else:
                value = request.path  # this is silly but simple


loop = asyncio.get_event_loop()
loop.create_task(irc_server())
loop.create_task(irc_server())

loop.run_forever()
点赞