长 运行 任务上的 Asyncio
Asyncio on long running task
我昨天刚用 python 3.5 学习了异步。
这是我今天要完成的事情。
import asyncio
import time
import requests
async def foo():
"""Some Long Running Taks"""
requests.get("")
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 吗?
您的 time.sleep()
正在阻塞;你需要使用 asyncio.sleep()
.
为什么你 运行 你的 loop
在 while True
里面?
还要注意 asyncio
只会帮助加速 io-bound 任务(例如从网络获取数据)。它不会帮助您加快 cpu 绑定的任务。为此你需要 threads or multiplrocessing.
看到你已经更新了你的问题,这里是我的回答中的一个小更新:requests
也被阻塞并且不能很好地与 asyncio
一起玩。 aiohttp
的功能相似,但与 asyncio
配合得很好
您的代码中存在一些问题:
requests 不支持 asyncio,请改用 aiohttp。
你的协程只有在循环 运行ning 时才会 运行:在你的代码中只调用 loop.run_until_complete()
一次,并安排很多(短或长)使用 await
(或 asycio.ensure_future()
或 loop.create_task()
)的任务。
这是一个与您尝试做的事情类似的示例:
# 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()
这是 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)
我昨天刚用 python 3.5 学习了异步。
这是我今天要完成的事情。
import asyncio
import time
import requests
async def foo():
"""Some Long Running Taks"""
requests.get("")
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 吗?
您的 time.sleep()
正在阻塞;你需要使用 asyncio.sleep()
.
为什么你 运行 你的 loop
在 while True
里面?
还要注意 asyncio
只会帮助加速 io-bound 任务(例如从网络获取数据)。它不会帮助您加快 cpu 绑定的任务。为此你需要 threads or multiplrocessing.
看到你已经更新了你的问题,这里是我的回答中的一个小更新:requests
也被阻塞并且不能很好地与 asyncio
一起玩。 aiohttp
的功能相似,但与 asyncio
您的代码中存在一些问题:
requests 不支持 asyncio,请改用 aiohttp。
你的协程只有在循环 运行ning 时才会 运行:在你的代码中只调用
loop.run_until_complete()
一次,并安排很多(短或长)使用await
(或asycio.ensure_future()
或loop.create_task()
)的任务。
这是一个与您尝试做的事情类似的示例:
# 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()
这是 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)