Python asyncio创建要永远运行的任务

Python asyncio创建要永远运行的任务,python,python-3.x,python-asyncio,Python,Python 3.x,Python Asyncio,我有以下代码 import asyncio loop = asyncio.get_event_loop() async def while_loop(): n = 0 while True: print(f"{n}") await asyncio.sleep(2) n = n+1 async def some_func(): await asyncio.sleep(5) print("Some Func")

我有以下代码

import asyncio

loop = asyncio.get_event_loop()

async def while_loop():
    n = 0
    while True:
        print(f"{n}")
        await asyncio.sleep(2)
        n = n+1

async def some_func():
    await asyncio.sleep(5)
    print("Some Func")

future = loop.create_task(while_loop())
loop.run_until_complete(some_func())
我希望
while\u loop
函数永远运行,但它似乎只是在调用
run\u直到
后才执行,并且在
某些函数执行完毕后停止打印while循环。我看到的结果是:

0
1
2
Some Func
我希望即使在
某些功能完成后,数字仍能继续打印

0
1
2
Some Func
3
4
5
6
.
.
.
打印更多号码的唯一方法是再次调用
some_func

我希望即使在
某些功能完成后,数字仍能继续打印

0
1
2
Some Func
3
4
5
6
.
.
.
run\u until\u complete
的参数控制事件循环的运行时间。一旦事件循环停止运行,所有的协同程序都会被有效地挂起,而不仅仅是您一直在等待的那个。但你有不同的选择:

  • 循环。运行\u直到\u完成(some\u func())
    -您已经使用的内容;运行事件循环,直到
    some_func
    corroutine完成。在这段时间内也并行执行其他协程,但也会在事件循环完成后立即停止执行它们

  • -运行事件循环,直到某个协程或回调调用
    loop.stop()
    。如果它们都不这样做,那么即使所有的协程都结束了,事件循环也不会停止。在您的情况下,可以调用
    loop.create_task(while_loop())
    ,然后调用
    loop.create_task(some_func())
    ,然后调用
    loop.run_forever()

  • loop.run\u直到\u完成(asyncio.gather(while\u loop(),some\u func())
    运行事件循环直到两个指定的协程完成。这(等待所有任务)显然是您所期望的
    循环。运行\u直到\u complete()
    自动执行,即使您只指定了一个,但它不是这样工作的,它会在指定的协同程序完成后立即停止。可用于同时等待多个协同路由。有关更精细的等待控制,请参见


由于您的一个协同程序将永远运行,最后两个选项将是等效的,并将产生预期的输出。

这就是我用来保持
上下文永远保持异步的方法:

def never():
    try:
        return never.never
    except AttributeError:
        never.never = asyncio.Future()
        return never.never


async def create_context_and_dependent_tasks():
    async with create_ctx() as ctx:
        for i in range(10):
            asyncio.create_task(use_ctx_indefinitely(bar))

        await never()   # **THIS** is the main idea I wanted to talk about.
它不适用于多个循环,但很少出现这种情况(可以通过稍微修改
never
函数来解决):

问题是,如果你创造了一个本地未来:

async def foo():
    never = asyncio.Future()
    await never

它将被收集垃圾,任务将被销毁。。。只是因为Python充满了惊喜。因此,您必须全局创建未来(但不是最初,因为循环还不存在)。

现在,如果我想稍后在某个随机时间运行
某些函数(和其他函数),那么最好在单独的线程中运行新的循环吗?否则,<代码> RuniGoiely正在阻塞主线程循环。@ SCORE认为协同程序可以启动其他协同程序。因此,您调用的
run_ever
并不意味着整个程序被卡住,或者您不能为事件循环添加新的内容。典型的asyncio程序是围绕为整个应用程序提供服务的事件循环构建的。只有在需要将asyncio引入遗留代码库(问题没有指出)的情况下,才需要在后台线程中使用事件循环。嗯,我想知道在Jupyter笔记本中测试代码时是否看到奇怪的行为。loop.run_forever()无限期地阻止我在loop.get_event_loop()之后执行它的那一刻。我希望执行loop.run_forever(),然后能够创建添加到循环中的任务。这是错误的想法吗?本质上,我正在探索从RESTful API检索的数据,但我不知道这些数据是如何排列的。因此,我点击1000个URL来收集数据,然后对其进行分析,以了解下一步可能要抓取的其他端点。@slaw请记住,asyncio不是线程化的-您不能同时完成
运行,直到\u complete()
并让数字继续打印。asyncio是为整个程序在事件循环中运行而设计的。因此,如果您正在探索使用REST检索的数据,那么就编写一个检索数据并对其进行分析的协同路由(如果需要,可以生成其他协同路由)。该协程可以由简单的
while True
循环组成,也可以包含任意复杂的逻辑。使用
循环启动协同程序。创建任务()
,运行
循环。永远运行()
,然后让它完成其余的工作。最后,明确说明如何在
运行后将任务添加到循环中,直到\u完成()
阻塞主线程。