2017-06-16 2 views
1

J'ai écrit un exemple de code de mon problème. Les messages d'entrée sont divisés en morceaux fixes et mélangés en utilisant un délai aléatoire intentionnel. Cependant, sleep() bloque et n'exécutera pas la tâche suivante. Est-ce possible sur un seul thread ou dois-je recourir au multi-threading?Comment asynchrone tâche de planification de non-bloc ou un événement déclenché en Python?

from random import randint 
from time import sleep 

def delay_message(split_message, delay): 
    #sleep(delay) #this blocks 
    print("Shuffled message: {} and time: {}". format(split_message, delay)) 

def main(): 
    message = raw_input('Input: ') 

    #padding 
    difference = len(message) % 5 
    message=message.ljust(len(message)+5-difference, "0") 

    for i in range(0, len(message), 5): 
     delay = randint(0, 5) 
     split_message = message[i:i+5] 
     delay_message(split_message, delay) 

if __name__ == "__main__": 
    main() 
+0

jetez un oeil à ['asyncio'] (https://docs.python.org/3/library/asyncio.html). Si c'est vraiment juste un sommeil non bloquant dont vous avez besoin, cela pourrait vous aider. –

Répondre

1

sleep va en effet bloquer le fil de la course.

Il est possible de le rendre non-bloquant en utilisant des bibliothèques comme gevent. Gevent peut également corriger time.sleep et le rendre non-bloquant et possède également son propre sommeil non-bloquant. Il peut aussi patcher toute la librairie standard python pour la rendre non bloquante - socket, temps, threading etc, voir documentation.

L'exemple ci-dessus peut être fait en même temps de en collaboration avec gevent comme ceci:

from random import randint 
from gevent import sleep, spawn, joinall 

def delay_message(split_message, delay): 
    # Gevent's sleep yields the event loop for 
    # duration of delay rather than blocking the running thread 
    sleep(delay) 
    print("Shuffled message: {} and time: {}". format(split_message, delay)) 

def main(): 
    message = raw_input('Input: ') 

    #padding 
    difference = len(message) % 5 
    message=message.ljust(len(message)+5-difference, "0") 

    greenlets = [] 
    # This will create len(message)/5 number of greenlets, 
    # which corresponds to the concurrency level. 
    # Greenlets all run under one thread so there is no CPU 
    # overhead here. 
    for i in range(0, len(message), 5): 
     delay = randint(0, 5) 
     split_message = message[i:i+5] 
     greenlets.append(spawn(delay_message, split_message, delay)) 
    # Wait for all greenlets to complete, raise any exceptions 
    joinall(greenlets, raise_error=True) 

if __name__ == "__main__": 
    main() 

La contrainte est que les tâches liées CPU ne peuvent pas être exécutés dans greenlets car ils bloqueraient la boucle d'événements et tous les autres greenlets.

Tant que ce qui est exécuté dans les maillages est lié aux E/S, comme le fait de passer des messages dans des sockets ou des générateurs, d'autres verdlets et autres, des petits trous sont appropriés. Pour les tâches liées à la CPU, utilisez des threads natifs ou plusieurs processus.

Il existe d'autres alternatives comme asyncio (Py3 uniquement). Gevent est compatible avec Py2 et 3 et a des performances très élevées, soutenues par des extensions de code natives.

+0

Merci, c'est très intéressant. En termes de CPU, voulez-vous dire si delay_message effectuait une opération lourde? Ou pourriez-vous me donner un exemple de ce que vous entendez par – Anderson

+0

tâche liée à l'UC serait tout ce qui est bloqué lors de l'exécution du code sur le CPU. Des exemples seraient le codage et le décodage audio/vidéo, le traitement d'image et ainsi de suite, essentiellement tout ce qui implique un code s'exécutant sur la CPU. Les tâches liées aux E/S seraient la lecture/l'écriture de flux sur le réseau, la gestion des requêtes réseau, les E/S de disque, etc. La mise en réseau peut également être gérée par des threads, mais cela implique beaucoup de temps système (augmentation de l'utilisation du processeur, réduction de la concurrence maximale) pour un élément qui n'est pas limité par le processeur. Pour cela, le multitâche coopératif, aussi connu sous le nom d'E/S asynchrones, est un meilleur choix. – danny

+0

qui a du sens, merci pour cela. Gevent n'a pas 'usleep() ou nanosleep()' avec un haut degré de précision. Y at-il un moyen de gérer cela avec la méthode actuelle? Ou pourriez-vous conseiller une autre façon que je pourrais regarder dans – Anderson