为什么我在Python asyncio中遇到“任务被破坏但是有待处理”的错误?

时间:2015-03-27 18:27:04

标签: python python-asyncio aiohttp

我使用asyncio和漂亮的aiohttp。主要的想法是我向服务器发出请求(它返回链接),然后我想从并行中的所有链接下载文件(类似于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())

但是,当我尝试运行它时,我有很多“下载...”输出和

Task was destroyed but it is pending!

没有'OK + filename'。

我该如何解决?

1 个答案:

答案 0 :(得分:12)

您忘记yield fromasyncio.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要销毁的任务,以及你看到要显示的警告。