Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/352.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在异步任务之间自由切换的正确方法是什么?_Python_Python 3.x_Asynchronous_Python Asyncio - Fatal编程技术网

Python 在异步任务之间自由切换的正确方法是什么?

Python 在异步任务之间自由切换的正确方法是什么?,python,python-3.x,asynchronous,python-asyncio,Python,Python 3.x,Asynchronous,Python Asyncio,假设我有一些异步运行的任务。它们可能是完全独立的,但我仍然希望设置TAK暂停的点,以便它们可以同时运行 同时运行任务的正确方法是什么?我目前正在使用wait asyncio.sleep(0),但我觉得这会增加很多开销 import asyncio async def do(id, amount): for i in range(amount): # Do some time-expensive work print(f'{id}: has done {i

假设我有一些异步运行的任务。它们可能是完全独立的,但我仍然希望设置TAK暂停的点,以便它们可以同时运行

同时运行任务的正确方法是什么?我目前正在使用
wait asyncio.sleep(0)
,但我觉得这会增加很多开销

import asyncio

async def do(id, amount):
    for i in range(amount):
        # Do some time-expensive work
        print(f'{id}: has done {i}')

        await asyncio.sleep(0)

    return f'{id}: done'

async def main():
    res = await asyncio.gather(do('Task1', 5), do('Task2', 3))
    print(*res, sep='\n')

loop = asyncio.get_event_loop()

loop.run_until_complete(main())
输出 如果我们使用简单的生成器,空的
yield
将暂停任务流,而不会产生任何开销,但是空的
wait
无效


在没有开销的情况下,设置此类断点的正确方法是什么?

如注释中所述,通常异步IO协同路由会自动挂起将阻塞或休眠在等效同步代码中的调用。在您的情况下,协程是CPU限制的,因此等待阻塞调用是不够的,它需要偶尔将控制权交给事件循环,以允许系统的其余部分运行

在协作式多任务处理中,显式产出并不少见,使用
await asyncio.sleep(0)
会带来风险:睡眠太频繁,通过不必要的切换降低计算速度;睡眠太少,你在一个单一的协同过程中花费了太多的时间,从而占据了事件循环

asyncio提供的解决方案是使用将CPU绑定的代码卸载到线程池。等待它将自动暂停协同路由,直到CPU密集型任务完成,而无需任何中间轮询。例如:

import asyncio

def do(id, amount):
    for i in range(amount):
        # Do some time-expensive work
        print(f'{id}: has done {i}')

    return f'{id}: done'

async def main():
    loop = asyncio.get_event_loop()
    res = await asyncio.gather(
        loop.run_in_executor(None, do, 'Task1', 5),
        loop.run_in_executor(None, do, 'Task2', 3))
    print(*res, sep='\n')

loop = asyncio.get_event_loop()
loop.run_until_complete(main())

此外,断点在这里可能不是正确的术语。请随意使用正确的术语进行评论或更新。“但我仍然想设置一些断点,以便它们可以同时运行”-是的,断点肯定不是正确的词,但我无法说出您要的是什么,或者它是否有意义,更不用说有一个名称了。您是否试图写一行这样的话“您可以在这里随意切换协同程序"? 你不需要手动操作;如果要进行缓慢的网络调用,asyncio应该在需要等待网络通信时为您切换,如果要进行缓慢而繁重的计算,那么这可能根本不属于事件循环。我看到您已经编辑了您的帖子。您有什么特别的原因想暂停您的合作计划吗?关于你的情况,有什么能让你更快地完成工作吗?@user2357112是的,听起来像是“在这里随意切换任务”。假设我有两个任务需要尽可能频繁地进行一些测量。我不希望它们一个接一个地运行,但我也不希望它们等待任何精确的时间。如果这不是正确的方法,请随意指出这是我的一个范例错误。
import asyncio

def do(id, amount):
    for i in range(amount):
        # Do some time-expensive work
        print(f'{id}: has done {i}')

    return f'{id}: done'

async def main():
    loop = asyncio.get_event_loop()
    res = await asyncio.gather(
        loop.run_in_executor(None, do, 'Task1', 5),
        loop.run_in_executor(None, do, 'Task2', 3))
    print(*res, sep='\n')

loop = asyncio.get_event_loop()
loop.run_until_complete(main())