Bienvenue sur IndexError.

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

Mais aussi sur les technos front comme React, Angular, Typescript et Javascript en général.

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)
...