为什么我在 Python asyncio 中收到 "Task was destroyed but it is pending" 错误?

Why am I getting a "Task was destroyed but it is pending" error in Python asyncio?

我用asyncio又漂亮aiohttp。主要思想是我向服务器发出请求(它是 returns 链接),然后我想从 parallel 中的所有链接下载文件(类似于 example).

代码:

import aiohttp
import asyncio

@asyncio.coroutine
def downloader(file):
    print('Download', file['title'])
    yield from asyncio.sleep(1.0) # some actions to download
    print('OK', file['title'])


def run():
    r = yield from aiohttp.request('get', 'my_url.com', True))
    raw = yield from r.json()
    tasks = []
    for file in raw['files']:
        tasks.append(asyncio.async(downloader(file)))
        asyncio.wait(tasks)

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(run())

但是,当我尝试 运行 它时,我有很多 "Download ..." 输出和

Task was destroyed but it is pending!

'OK + filename'.

什么都没有

我该如何解决?

您忘记 yield from 呼叫 asyncio.wait。您的缩进也可能有误;在遍历整个 raw['files'] 列表后,您只想 运行 它。这是修复了两个错误的完整示例:

import aiohttp
import asyncio

@asyncio.coroutine
def downloader(file):
    print('Download', file['title'])
    yield from asyncio.sleep(1.0) # some actions to download
    print('OK', file['title'])

@asyncio.coroutine
def run():
    r = yield from aiohttp.request('get', 'my_url.com', True))
    raw = yield from r.json()
    tasks = []
    for file in raw['files']:
        tasks.append(asyncio.async(downloader(file)))
    yield from asyncio.wait(tasks)

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(run())

如果不调用 yield fromrun 会在您遍历整个文件列表后立即退出,这意味着您的脚本会退出,导致一大堆未完成的 downloader 待销毁的任务,并显示您看到的警告。