Maison >développement back-end >Tutoriel Python >Introduction à la méthode d'implémentation du timer de boucle en Python (avec code)

Introduction à la méthode d'implémentation du timer de boucle en Python (avec code)

不言
不言avant
2019-03-14 11:13:0217032parcourir

Ce que cet article vous apporte, c'est une introduction à la méthode d'implémentation d'un minuteur de boucle en python (avec du code). J'espère qu'il a une certaine valeur de référence. vous sera utile.

Comment écrire un timer en python pour effectuer une certaine opération en boucle ?

Objet Timer

from threading import Timer
def hello(): 
    print "hello, world" 
   
t = Timer(10.0, hello) 
t.start()

Sortie après 10 secondes :

hello, world

Focus sur le code t = Timer(10.0, bonjour), python fournit un objet Timer, qui effectuera une opération après un temps spécifié ; sa forme complète :

class threading.Timer(interval, function, args=[], kwargs={})

interval est l'intervalle de temps, la fonction est un objet appelable, args et kwargs seront utilisés comme paramètres de fonction.

Remarque : la fonction ne sera exécutée qu'une seule fois et ne sera pas exécutée régulièrement, et Timer créera un nouveau thread lors de l'exécution de l'opération.

Il y a une légère différence entre Timer en python2 et python3 :

# python2.7
def Timer(*args, **kwargs):
    return _Timer(*args, **kwargs)
# python3.7
class Timer(Thread):
    pass

En python3, Timer est une sous-classe de Thread en python2, _Timer est une sous-classe de Thread et Timer est ; juste une usine de la méthode de classe _Timer.

Le code ci-dessus n'imprimera hello, world qu'une seule fois, puis quittera. Alors, comment imprimer à intervalles réguliers en boucle ?

Minuterie de boucle approximative

Une façon consiste à continuer à enregistrer une minuterie dans la fonction, afin que la fonction puisse continuer à être exécutée dans l'intervalle suivant

from threading import Timer
def hello(): 
    print "hello, world" 
    Timer(10.0, hello) .start()

t = Timer(10.0, hello) 
t.start()
Dans tous les autres sens Émettez un bonjour tout le monde en 10 secondes.

L'effet est obtenu, mais il semble y avoir un problème ici. Revenons au Timer lui-même, c'est un thread. Chaque fois que le cycle est interrompu, le système doit créer un thread puis le recycler, ce qui coûte très cher au système. Si l'intervalle de temps est très court, le système créera de nombreux threads à la fois, et ces threads seront difficiles à recycler rapidement, ce qui entraînera une consommation de mémoire système et de ressources CPU.

Il n'est donc pas recommandé de continuer à enregistrer un Timer dans la fonction.

Un minuteur de boucle plus pythonique

Voici une méthode plus pythonique :

from threading import _Timer
def hello():
     print "hello, world"
class RepeatingTimer(_Timer): 
    def run(self):
        while not self.finished.is_set():
            self.function(*self.args, **self.kwargs)
            self.finished.wait(self.interval)
t = RepeatingTimer(10.0, hello)
t.start()
Concentrez-vous sur la classe RepeatingTimer, qui hérite du threading._Timer, mais remplace le parent The run méthode de la classe. C'est ainsi que Python2 est écrit. RepeatingTimer en python3 devrait hériter de threading.Timer.

Pourquoi devrions-nous remplacer la méthode run de Thread ?

_Timer est une sous-classe Thread. Examinons d'abord l'utilisation de la classe Thread.

from threading import Thread
def hello():
     print "hello, world"
# 继承 Thread
class MyThread(Thread):
    # 把要执行的代码写到run函数里面 线程在创建后会直接运行run函数
    def run(self):
        hello()
t = MyThread()
t.start()
Définition complète de l'objet Thread :

class threading.Thread(group=None, target=None, name=None, args=(), kwargs={})
Le code de la méthode run :

class Thread(_Verbose):
    def run(self):
        try:
            if self.__target:
                self.__target(*self.__args, **self.__kwargs)
        finally:
            # Avoid a refcycle if the thread is running a function with
            # an argument that has a member that points to the thread.
            del self.__target, self.__args, self.__kwargs
La méthode run standard est utilisée pour exécuter le constructeur passé dans par l'utilisateur La méthode cible. Les sous-classes peuvent remplacer la méthode run et écrire le code à exécuter dans run. Une fois le thread créé, la méthode run() sera exécutée lorsque l'utilisateur appelle la méthode start().

Ainsi, RepeatingTimer remplace la méthode run() de _Timer, ce qui peut modifier le corps d'exécution du thread. Lorsque nous appelons la méthode start() de RepeatingTimer, notre méthode run() remplacée sera exécutée.

Regardez l'instruction while not self.finished.is_set() dans la classe RepeatingTimer. self.finished.is_set() ne quittera pas la boucle avant la fin de True et le minuteur. terminé est un objet threading.Event. Un objet Event gère un indicateur, qui peut être défini sur True par la méthode set() ou défini sur False par la méthode clear(). Lors de l'appel de wait([timeout]), le thread se met en veille jusqu'à ce que l'indicateur soit True ou que l'indicateur soit défini sur True. le délai d'attente expire.

Nous savons que le timer dispose d'une méthode Cancel() qui permet d'annuler l'opération à l'avance. Il appelle en fait la méthode Event.clear() pour laisser la méthode d'attente terminer l'attente à l'avance et détermine que l'opération de minuterie ne sera pas effectuée lorsque l'indicateur est vrai. Code spécifique :

class _Timer(Thread):
    """Call a function after a specified number of seconds:
            t = Timer(30.0, f, args=[], kwargs={})
            t.start()
            t.cancel() # stop the timer's action if it's still waiting
    """

    def __init__(self, interval, function, args=[], kwargs={}):
        Thread.__init__(self)
        self.interval = interval
        self.function = function
        self.args = args
        self.kwargs = kwargs
        self.finished = Event()

    def cancel(self):
        """Stop the timer if it hasn't finished yet"""
        self.finished.set()

    def run(self):
        self.finished.wait(self.interval)
        if not self.finished.is_set():
            self.function(*self.args, **self.kwargs)
        self.finished.set()
Ainsi, la méthode run de RepeatingTimer exécutera toujours le corps de la boucle while. Dans le corps de la boucle, l'objet fonction transmis par l'utilisateur sera exécuté et attendra le temps spécifié. Lorsque l'utilisateur souhaite quitter le timer, il lui suffit d'appeler la méthode Cancel et de définir l'indicateur sur True afin que le corps de la boucle ne continue pas à s'exécuter. Ceci complète un assez bon chronomètre de boucle.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer