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.

Comment faire tourner différentes fonctions à différentes périodicités?

+2 votes

Je dispose de deux fonctions (qu'on appellera fonction A et fonction B) qui sont supposées récupérer des infos sur un serveur.

J'aimerais que la fonction A soit exécutée toutes les secondes, pendant que la fonction B est exécutée toutes les minutes.

J'ai essayé d'utiliser asyncio et de placer un "await asyncio.sleep(1)" (ou 60 pour la fonction B), mais ça ne fonctionne pas.

J'ai cru comprendre qu'on pouvait scheduler des coroutines avec asyncio, mais je n'ai rien trouvé de tel dans la doc.

demandé 29-Jun par Cornoualis (184 points)

Déjà il faudrait comprendre pourquoi ce que tu as fait ne fonctionne pas (et sans code ça risque d’être difficile).

Sinon : tu es obligé d'utiliser asyncio ? Pour quelle raison ? As-tu essayé avec des threads et un bon vieux time.sleep() dans une boucle infinie pour chaque fonction ?

Je n'ai pas de raison particulière d'utiliser asyncio sinon que:
1°) J'aimerais apprendre ce paradigme de programmation
2°) Il semblerait que ce soit la meilleure approche lorsqu'on veut lancer des centaines de fonctions concurrentes

1 Réponse

+3 votes
 
Meilleure réponse

Un exemple avec Thread :

from time import sleep
from threading import Thread

def A(pause=1):
    while True:
        print('A')
        sleep(pause)

def B(pause=60):
    while True:
        print('B')
        sleep(pause)

t1 = Thread(target=A)
t2 = Thread(target=B)
t1.start()
t2.start()
t1.join()
t2.join()

Le même en asyncio :

import asyncio

async def A(pause=1):
    while True:
        print('A')
        await asyncio.sleep(pause)

async def B(pause=60):
    while True:
        print('B')
        await asyncio.sleep(pause)

loop = asyncio.get_event_loop()
loop.run_until_complete(
    asyncio.gather(A(), B())
)
loop.close()

Bien évidement, il est plus propre d'encapsuler les appels à tes fonctions dans une fonction/coroutine qui est uniquement dédiée à la gestion du temps. Exemple avec asyncio :

import asyncio

async def run_periodically(fun, pause):
    """recoit une fonction sans argument, 
    utiliser functools.partial si necessaire"""
    while True:
        fun()
        await asyncio.sleep(pause)

A = lambda: print('A')
B = lambda: print('B')

loop = asyncio.get_event_loop()
loop.run_until_complete(
    asyncio.gather(run_periodically(A, 1),
                   run_periodically(B, 60))
)
loop.close()
répondu 30-Jun par yoch (2,066 points)
sélectionné 1-Jul par Cornoualis
...