0
votes

Existe-t-il une bibliothèque python ou une solution qui s'exécutera à une note minute ou à une heure?

Mon objectif est d'exécuter un programme sur différents ordinateurs et d'obtenir des données provenant de mesures. Le problème est que ces mesures doivent se produire en même temps (autant que possible). Mon approche actuelle consiste à installer Crony pour synchroniser l'heure de toutes les machines et démarrer un programme Python qui prendra des mesures au début de chaque minute. Cela s'est révélé être assez difficile à manier car je dois interroger le temps.time () dans une boucle et vérifier si nous sommes entrés dans une nouvelle minute. xxx

existe une solution standard pour ce type de problème ou au moins une solution plus élégante?


8 commentaires

Est-ce que cela répond à votre question? Comment dormir jusqu'à ce qu'un temps spécifique aaaaaa-mm -DD ​​HH: MM: SS?


Non, pas vraiment, la solution proposée est de calculer combien de temps il faudrait jusqu'à la prochaine invocation d'un point relatif à temps. Je dois effectuer une action exactement à la minute, en tant que résolution bien une résolution, une CPU peut fournir.


La plupart des systèmes d'exploitation ont un moyen de planifier des programmes à exécuter à certains moments (comme le planificateur de tâches de CronTab ou Windows). Il serait plus manipulé si vous vous êtes débarrassé de toute la logique de planification de Python, et il suffit d'utiliser un outil de système d'exploitation pour la planification.


@ Nog642 Votre commentaire est bon Général Conseils, mais ne s'applique pas au cas d'utilisation indiqué par OP . L'utilisation d'un outil de système d'exploitation comme Cron signifie que Python devrait être démarré à chaque fois à nouveau, ce qui peut prendre du temps, surtout si le programme importe des cadres tiers complexes tels que Asyncio, Aiohttp, Pandas, etc. L'OP a déclaré le désir de démarrer l'action. "Exactement à la minute, dans une résolution aussi fin une résolution qu'un processeur peut fournir" et la combinaison de cron avec l'interprète Startup semble assez loin de cela.


@ user4815162342 Merci beaucoup pour une explication supplémentaire du problème, c'est exactement le problème, je peux faire du traitement avant d'écrire les résultats des mesures et les écrire à la queue en une minute, mais uniquement si le processus est déjà en cours d'exécution.


La partie que je ne comprends pas est la raison pour laquelle vous ne calculez pas simplement l'intervalle de temps (point flottant) entre maintenant et le moment souhaité, et ASYNCIO.SLEEP (intervalle) . Avez-vous essayé cela?


@ user4815162342 Il suffit de dormir une quantité de temps fixe introduire une dérive de temps, je veux vérifier avec le système d'exploitation à chaque intervalle, assurez-vous que je suis toujours synchronisé avec le reste des systèmes.


Je pourrais avoir tort, mais cela ressemble à vous avoir besoin de plus de précision que de systèmes tels que Asyncio peut vraiment livrer, vraiment. Bonne chance!


3 Réponses :


0
votes

Peut-être que c'est ce que vous recherchez

Quelle est la meilleure façon d'exécuter à plusieurs reprises une fonction toutes les x secondes de Python?

ne peut pas commenter car je n'ai pas la réputation T.T


3 commentaires

Désolé, j'ai examiné cette question, mais Sched Library ne semble pas avoir de mise en œuvre permettant de démarrer une tâche à une heure exacte. Et même si je manipule que je ne sais pas si cela ne commencera pas à dériver après un certain temps (comme l'heure de l'heure (60) due), je dois prendre des mesures sur une longue période.


Votre problème ne serait-il pas résolu en utilisant un fil d'auditeur qui exécute votre programme avec un appel de cron? Le fil sera asynchrone et pourra attraper des envois. Toutefois, si le traitement prend> 1 min, je pense que vous devriez pouvoir implémenter le multitraitement pour exécuter les tâches en parallèle en cas de chevauchement. Je pense que cette approche supprimerait les coûts de démarrage comme mentionné dans les autres commentaires


Oui, une tâche d'auditeur dans la boucle ASYNC à l'écoute de certains signaux qu'un script Bash envoyer de Cron pourrait être une solution. Je pense en quelque sorte que ce serait plus compliqué que de courir mon propre planificateur.



0
votes

Essayez ceci:

import asyncio
import time
from datetime import datetime


async def task(call_time):
    print(f"task started at: {to_string(call_time)}")
    await asyncio.sleep(5)
    print(f"task finished at: {to_string((time.time()))}")


def to_string(t):
    return datetime.utcfromtimestamp(t).strftime('%Y-%m-%d %H:%M:%S')


def call_task(loop, task, *args):
    print("task creating")
    loop.create_task(task(*args))
    print("task created")


async def main(loop: asyncio.AbstractEventLoop):
    interval = 10
    t = time.time()
    while True:
        print(f"Now is {to_string(t)}")
        call_time = estimate_next_call(t, interval)
        print(f"Call time {to_string(call_time)}")
        await asyncio.sleep(call_time - t)
        call_task(loop, task, call_time)
        t += interval
        await asyncio.sleep(interval)


def estimate_next_call(t, interval):
    return ((t + interval) // interval) * interval


if __name__ == "__main__":
    event_loop = asyncio.get_event_loop()
    event_loop.run_until_complete(main(event_loop))


2 commentaires

Bienvenue à Stackoverflow! Pouvez-vous fournir une explication pour compléter le code de votre réponse? Comment ce code résoudra-t-il le problème ou comment avez-vous amélioré le code utilisé dans la question?


Je suis désolé, cette solution ne semble pas prendre en compte que le début de l'intervalle doit être exactement au début de tout ce qui est choisi comme intervalle par exemple. Le code par minute doit détecter exactement le début d'une minute. En outre, cela n'inclut aucune sorte de mécanisme permettant d'éviter la dérive du temps qui serait introduit en dormant simplement pendant x secondes. Mais merci.



0
votes

J'ai essayé d'utiliser bibliothèque APSCHEDuler car il semble avoir une expression cron mise en œuvre, cependant J'ai trouvé 2 descentes avec cette approche. Il conviendrait que la bibliothèque s'intègre au code Asyncio plutôt étrange, doit être la faute de ma mise en œuvre. Deuxième problème est qu'il faut quelques millisecondes pour la tâche planifiée pour commencer à courir, c'est une question mineure, mais la planification à la main évite le décalage, et je souhaite obtenir des mesures aussi proches que possible de "l'heure exacte"

J'ai aussi essayé d'utiliser CELERY Beat , ceci Cependant, semble être une overcilleuse majeure, avoir à installer Redis ou autre chose en tant que courtier de messages, et en utilisant un cadre aussi complexe pour une telle tâche mineure hurle simplement «faux». p>

solution actuelle qui fonctionne assez vite. Lors de la modification de la résolution des chèques de temps à l'aide de "time_factor" pour modifier les valeurs du temps.time () en secondes. La partie principale de la solution divise l'heure actuelle avec l'intervalle afin d'obtenir le numéro cordial de l'intervalle de l'historique, si ce numéro a changé, nous venons de saisir le nouvel intervalle: P>

time_factor = 100  # 1000 for milliseconds
interval_size = 60 * time_factor
sleep_time = 1 / (time_factor * 100)
old_interval = int(int(time.time()*time_factor) / interval_size)
current_timestamp = time.time()
current_interval = None

running = True
while running:
    current_timestamp = int(time.time() * time_factor)
    current_interval = int(t_s / interval_size)
    if (current_interval != old_interval):
        request_runtime = time.time()

        await self.do_time_sensitive_work()

        old_interval = current_interval
        request_runtime = time.time() - request_runtime
        await asyncio.sleep(1/(time_factor*100) - request_runtime )
    else:
        await asyncio.sleep(1/(time_factor*100))


0 commentaires