Asyncio长时间运行的任务

时间:2016-12-23 11:56:29

标签: python python-asyncio

昨天我刚学会了与python 3.5异步。

这就是我今天想要完成的事情。

import asyncio  
import time
import requests

async def foo():
    """Some Long Running Taks"""
    requests.get("http://stackoverflow.com/questions/41301031/asyncio-on-long-running-task")
    print("foo")

async def bar():
    """Some Quick Task"""
    print("bar")

while True:
    loop = asyncio.get_event_loop()
    loop.run_until_complete(asyncio.gather(foo(), bar()))
    loop.close()
    time.sleep(2)

#Expected output
"""
>>>bar
>>>bar
>>>bar
>>>bar
>>>bar
>>>foo
and so on
"""

这可以使用python async / await吗?

3 个答案:

答案 0 :(得分:2)

您的代码中存在一些问题:

  1. 请求不支持asyncio,请改用aiohttp

  2. 您的couroutines仅在循环运行时运行:仅在代码中调用loop.run_until_complete()一次,并使用await(或asycio.ensure_future()安排许多(短期或长期)任务}或loop.create_task())。

  3. 以下是一个与您尝试的操作类似的示例:

    # make sure to run `pip install aiohttp` first!!!
    
    import asyncio
    
    import aiohttp
    
    
    async def slow_fetch(delay):
        url = "http://httpbin.org/delay/{}".format(delay)
        print("Getting ", url)
        async with aiohttp.ClientSession() as session:
            async with session.get(url) as resp:
                text = await resp.text()
        print("Got {}, {} chars".format(url, len(text)))
    
    
    async def quick_loop():
        print("enter quick_loop")
        for i in range(10):
            await asyncio.sleep(1)
            print("quick_loop", i)
        print("exit quick_loop")
    
    
    loop = asyncio.get_event_loop()
    loop.run_until_complete(asyncio.gather(
        slow_fetch(3),
        slow_fetch(4),
        quick_loop(),
    ))
    loop.close()
    

答案 1 :(得分:0)

你的time.sleep()正在阻止;你需要使用asyncio.sleep()

为什么在loop内运行while True

还要注意asyncio只会帮助加速io-bound任务(例如从网上获取数据)。它不会帮助你加速cpu绑定的任务。为此,您需要threadsmultiplrocessing

看到您更新了问题,我的回答中有一个小更新:requests也阻止了,asyncio的效果不佳。 aiohttp的功能类似,但与asyncio

配合得很好

答案 2 :(得分:0)

这是ensure_future / create_task的更好方法: 使用装饰器

def async_wrap(func):
@wraps(func)
async def run(*args, loop=None, executor=None, **kwargs):
    if loop is None:
        loop = asyncio.get_event_loop()
    pfunc = partial(func, *args, **kwargs)
    return await loop.run_in_executor(executor, pfunc)

return run

现在,如果您有运行时间较长的功能(例如使用requests的功能),则可以执行以下操作:

@async_wrap
def long_running_function():
    return requests.get(_URL)