Python 警告:不等待协程“create_task”

问题描述 投票:0回答:1

我正在使用 Python 和 PyCharm,我正在尝试使用

asyncio
卸载数据库写入,但在 IDE 警告方面遇到问题

在我的 main.py 中,我以这种方式启动任务

db_logging_monitoring_task = asyncio.create_task(start_logging_jobs_sniffer())
tasks.append(db_logging_monitoring_task)
await gather(*tasks)

其中

start_logging_jobs_sniffer
是异步函数内的 while 循环

# Waits on jobs from a jobs_queue
async def start_logging_jobs_sniffer(self):
    while True:
        try:
            job = await self.logging_jobs_queue.get()


# Adds jobs to a jobs_queue
async def make_logging_job(self, params):
    job = self.LoggingJob(params)
    await self.logging_jobs_queue.put(job)

类似地,在 main.py 中,我有另一个后台监控任务,它以 5 秒的间隔进行轮询,然后记录轮询结果

async def poll(self, interval: int):
    if self.is_config_applied:
        while True:
            # ...

            asyncio.create_task(make_logging_job(
                params={
                    **self.polling_results
                },
            ))

但是 pycharm 向我发出警告

Coroutine 'create_task' is not awaited 

我特别希望

make_logging_job
任务与其他任务并行工作,这就是我不使用
await
的原因,这似乎按预期工作。

如果我在出现警告的情况下运行,

make_logging_job
似乎是并行的并且不会阻止任何东西

我非常不明白为什么 PyCharm 会发出警告,表示未等待

create_task
,是否还有其他更好的方法来执行任务?

编辑:

将任务保存到变量可以抑制错误,并且似乎通过在后台运行东西来发挥作用

            test = asyncio.create_task(make_logging_job(
                params={
                    **self.polling_results
                },
            ))

但我不知道为什么这有帮助,将任务保存到变量不会等待我假设的协程

python asynchronous pycharm python-asyncio coroutine
1个回答
0
投票

当您创建异步任务时,您不能只是“触发并忘记”它 - 您必须在某处保留对它的引用 - 并最终检查它是否完成,以便您可以丢弃您的引用。

正如您发现的(在评论中) - 需要将任务归因于局部变量 - 但与您的 IDE 报告不同,这还不够 - 就像只是归因于变量并丢弃它一样,您将没有参考。

使用容器,如

set()
,并生成另一个任务来检查它们是否完成,可能使用
asyncio.wait
调用:

import asyncio

all_jobs = set()

async def poll(self, interval: int):
    if self.is_config_applied:
        while True:
            # ...
            
            all_jobs.add(asyncio.create_task(make_logging_job(
                params={
                    **self.polling_results
                },
            )))

asyncio def task_waiter():
    while True:
        pending, done = await asyncio.wait(all_jobs, timeout=10) # collect once each 10 seconds - change at your will
        all_jobs.clear()
        all_jobs.update(pending)


# and wherever in your code, where you call `poll`, instead of
# just `await poll` do:

async def main(...):
    ...
    # await poll(...)  #old code, commented out
    poll_task = asyncio.create_task(poll(...))
    waiter_task = asyncio.create_task(task_waiter())
    await asyncio.gather(poll_task, waiter_task)




© www.soinside.com 2019 - 2024. All rights reserved.