Bienvenue sur IndexError.

Ici vous pouvez poser des questions sur Python et le Framework Django.

Consultez la FAQ pour améliorer vos chances d'avoir des réponses à vos questions.

Asyncio: itérer sur un zip de futures et d'itérables

0 votes

Sur le code suivant, pour itérer sur des futures, j'utilise asyncio.as_completed.

import asyncio
from random import randint

async def get(url):
    r = randint(0, 3)
    await asyncio.sleep(r)
    return url

async def run():
    urls = ['https://www.google.be/', 'http://twitter.com/', 'http://facebook.com/', 'http://indexerror.net/']
    names = ['google', 'twitter', 'facebook', 'indexerror']

    tasks = [get(url) for url in urls]

    for task, name in zip(asyncio.as_completed(tasks), names):
        url = await task
        print(url, name)

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

Le résultat de la requête est aléatoirement:

http://indexerror.net/ google
http://facebook.com/ twitter
http://twitter.com/ facebook
https://www.google.be/ indexerror

Le code ressemble à du synchrone, mais le comportement asynchrone amène ici à des comportements non souhaités. En supprimant asyncio.as_completed, le code devient synchrone et on obtient:

https://www.google.be/ google
http://twitter.com/ twitter
http://facebook.com/ facebook
http://indexerror.net/ indexerror

Comment avoir ce même comportement en asynchrone?

demandé 10-Jul-2016 par sekun (134 points)

2 Réponses

0 votes
 
Meilleure réponse

Suite à la réponse de etno712, une implémentation possible serait alors:

#!/usr/bin/env python

import asyncio
from random import randint


async def get(url):
    r = randint(0, 3)
    await asyncio.sleep(r)
    return url

async def run():

    async def _get(url, name):
        return await get(url), name

    urls = ['https://www.google.be/', 'http://twitter.com/', 'http://facebook.com/', 'http://indexerror.net/']
    names = ['google', 'twitter', 'facebook', 'indexerror']

    tasks = [_get(url, name) for url, name in zip(urls, names)]

    for task in asyncio.as_completed(tasks):
        url, name = await task
        print(url, name)


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(run())
répondu 12-Jul-2016 par sekun (134 points)
sélectionné 18-Jul-2016 par sekun

Coche la coche verte si tu pense que c'est la solution. ça aidera les suivants

0 votes

Pour que cela marche, c’est ta fonction get qui doit retourner un couple (clé, résultat)

répondu 10-Jul-2016 par etno712 (288 points)
...