如何为Python Asyncio创建自定义事件

时间:2017-12-15 15:29:57

标签: python-3.x python-asyncio mesos marathon

Mesos调度程序Marathon具有异步HTTP API。例如。当通过将JSON发布到/v2/apps来部署应用程序时,将返回部署ID。然后,可以使用id在/v2/deployments中轮询部署状态,或者订阅/v2/events并查找deployment_success事件。

我想用协同程序创建一个异步Python客户端。例如。 client.deploy_app(...)事件到达后deployment_success应该返回,但不会阻止。

如何使用asyncio实现这些方法?如何创建事件监听器?感觉这是一个事件循环,但我不知道如何注册事件。

1 个答案:

答案 0 :(得分:1)

使用/v2/apps模块创建aiohttp所需的异步帖子http请求:

import asyncio
import aiohttp


async def post(url, json):
    async with aiohttp.ClientSession() as session:
        async with session.post(url, json=json) as resp:
            return await resp.json()


async def main():
    res = await post('http://httpbin.org/post', {'test': 'object'})
    print(res['json'])  # {'test': 'object'}


loop = asyncio.get_event_loop()
try:
    loop.run_until_complete(main())
    loop.run_until_complete(loop.shutdown_asyncgens())
finally:
    loop.close()

如果您想使用/v2/events来跟踪部署成功,您应该请求流(请参阅api doc)。它可以在aiohttp中使用asynchronous iteration实现:您只需异步读取内容,等待所需的事件,例如:

import asyncio
import aiohttp


async def stream(url):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as resp:
            async for line in resp.content:
                yield line


async def main():
    async for line in stream('http://httpbin.org/stream/10'):
        print(line)  # check if line contains event you need


loop = asyncio.get_event_loop()
try:
    loop.run_until_complete(main())
    loop.run_until_complete(loop.shutdown_asyncgens())
finally:
    loop.close()

如果您想使用/v2/deployments,请定期使用asyncio.sleep请求延迟。在这种情况下,您的功能不会被阻止:

import asyncio
import aiohttp


async def get(url):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as resp:
            return await resp.json()


async def main():
    while True:       
        # Make request to see if deplayment finished:
        res = await get('http://httpbin.org/get')
        print(res['origin'])  # break if ok here
        # Async wait before next try:
        await asyncio.sleep(3)


loop = asyncio.get_event_loop()
try:
    loop.run_until_complete(main())
    loop.run_until_complete(loop.shutdown_asyncgens())
finally:
    loop.close()