comment pourrais-je arrêter une boucle while après 5 minutes si elle n'atteint pas ce que je veux qu'elle réalise.
while true:
test = 0
if test == 5:
break
test = test - 1
Ce code me jette dans une boucle sans fin.
Essayez ce qui suit:
import time
timeout = time.time() + 60*5 # 5 minutes from now
while True:
test = 0
if test == 5 or time.time() > timeout:
break
test = test - 1
Vous voudrez peut-être aussi ajouter un court sommeil ici pour que cette boucle n'emballe pas le processeur (par exemple time.sleep(1)
au début ou à la fin du corps de la boucle).
Essayez ce module: http://pypi.python.org/pypi/interruptingcow/
from interruptingcow import timeout
try:
with timeout(60*5, exception=RuntimeError):
while True:
test = 0
if test == 5:
break
test = test - 1
except RuntimeError:
pass
Cordialement
Vous n'avez pas besoin d'utiliser la boucle while True:
dans ce cas. Il existe un moyen beaucoup plus simple d'utiliser directement la condition de temps:
import time
# timeout variable can be omitted, if you use specific value in the while condition
timeout = 300 # [seconds]
timeout_start = time.time()
while time.time() < timeout_start + timeout:
test = 0
if test == 5:
break
test -= 1
La réponse de Petr Krampl est la meilleure, à mon avis, mais il faut en dire plus sur la nature des boucles et sur la manière d'optimiser l'utilisation du système. Les débutants qui tombent sur ce fil peuvent être encore plus déconcertés par les erreurs logiques et algorithmiques de la question et les réponses existantes.
Premièrement, regardons ce que votre code fait comme vous l'avez écrit à l'origine:
while True:
test = 0
if test == 5:
break
test = test - 1
Si vous dites while True
dans un contexte de boucle, votre intention est normalement de rester dans la boucle pour toujours. Si ce n'est pas votre intention, vous devriez envisager d'autres options pour la structure de la boucle. Petr Krampl vous a montré un moyen parfaitement raisonnable de gérer cela, ce qui est beaucoup plus clair pour quelqu'un qui pourrait lire votre code. En outre, vous aurez plus de clarté plusieurs mois plus tard si vous devez revoir votre code pour ajouter ou corriger quelque chose. Un code bien écrit fait partie de votre documentation. Il y a généralement plusieurs façons de faire les choses, mais cela ne les rend pas toutes également valables dans tous les contextes. while true
en est un bon exemple, particulièrement dans ce contexte.
Ensuite, nous examinerons l’erreur algorithmique dans votre code original. La toute première chose que vous faites dans la boucle est d'affecter 0 à test
. La prochaine étape consiste à vérifier si la valeur de test
est 5, ce qui ne sera jamais le cas à moins que plusieurs threads modifient le même emplacement mémoire. Les discussions ne font pas partie de cette discussion, mais il convient de noter que le code pourrait fonctionner techniquement, mais que même avec plusieurs threads, il en manquerait beaucoup, par exemple. sémaphores. Quoi qu'il en soit, vous resterez dans cette boucle pour toujours, indépendamment du fait que la sentinelle force une boucle infinie.
L'instruction test = test - 1
est inutile quelle que soit sa fonction car la variable est réinitialisée au début de la prochaine itération de la boucle. Même si vous le changiez en test = 5
, la boucle serait toujours infinie car la valeur est réinitialisée à chaque fois. Si vous déplacez l'instruction d'initialisation en dehors de la boucle, elle aura au moins une chance de sortir. Ce que vous souhaitiez peut-être était quelque chose comme ceci:
test = 0
while True:
test = test - 1
if test == 5:
break
L'ordre des instructions dans la boucle dépend de la logique de votre programme. Cela fonctionnera dans l'un ou l'autre ordre, cependant, ce qui est le point principal.
Le prochain problème est l'erreur logique potentielle et probable de commencer à 0, en soustrayant continuellement 1 et en comparant ensuite avec un nombre positif. Oui, il y a des cas où c'est ce que vous avez l'intention de faire tant que vous en comprenez les implications, mais ce n'est probablement pas ce que vous vouliez. Les versions les plus récentes de python ne seront pas complètes lorsque vous atteindrez le "bas" de la plage d'un entier, tel que C, et de nombreux autres langages. Cela vous permettra de continuer à soustraire 1 jusqu'à ce que vous ayez rempli la mémoire disponible sur votre système ou au moins ce qui est alloué à votre processus. Regardez le script suivant et les résultats:
test = 0
while True:
test -= 1
if test % 100 == 0:
print "Test = %d" % test
if test == 5:
print "Test = 5"
break
qui produit ceci:
Test = -100
Test = -200
Test = -300
Test = -400
...
Test = -21559000
Test = -21559100
Test = -21559200
Test = -21559300
...
La valeur de test
ne sera jamais 5, cette boucle ne se fermera donc jamais.
Pour ajouter à la réponse de Petr Krampl, voici une version qui est probablement plus proche de ce que vous vouliez réellement en plus de sortir de la boucle après un certain temps:
import time
test = 0
timeout = 300 # [seconds]
timeout_start = time.time()
while time.time() < timeout_start + timeout:
if test == 5:
break
test -= 1
Il ne sera toujours pas cassé basé sur la valeur de test
, mais c'est une boucle parfaitement valide avec une condition initiale raisonnable. Une vérification supplémentaire des limites pourrait vous aider à éviter l'exécution d'une très longue boucle sans aucune raison, par exemple. vérifie si la valeur de test est inférieure à 5 à l'entrée de la boucle, ce qui romprait immédiatement la boucle.
Il convient de mentionner une autre chose à laquelle aucune autre réponse n’a été apportée. Parfois, lorsque vous faites une boucle comme celle-ci, vous ne souhaitez peut-être pas utiliser le processeur pendant tout le temps imparti. Par exemple, supposons que vous vérifiez la valeur de quelque chose qui change à chaque seconde. Si vous n'introduisez pas de délai, vous utiliseriez chaque cycle de processeur disponible attribué à votre processus. C'est bien si cela est nécessaire, mais une bonne conception permettra à de nombreux programmes de s'exécuter en parallèle sur votre système sans surcharger les ressources disponibles. Une simple instruction de mise en veille permettra de libérer la grande majorité des cycles de traitement alloués à votre processus afin que d'autres programmes puissent fonctionner.
L'exemple suivant n'est pas très utile, mais il illustre le concept. Disons que vous voulez imprimer quelque chose chaque seconde. Une façon de le faire serait la suivante:
import time
tCurrent = time.time()
while True:
if time.time() >= tCurrent + 1:
print "Time = %d" % time.time()
tCurrent = time.time()
La sortie serait la suivante:
Time = 1498226796
Time = 1498226797
Time = 1498226798
Time = 1498226799
Et l'utilisation du processeur de processus ressemblerait à ceci:
Cela représente une énorme quantité d’utilisation du processeur pour ne faire pratiquement aucun travail. Ce code est beaucoup plus agréable pour le reste du système:
import time
tCurrent = time.time()
while True:
time.sleep(0.25) # sleep for 250 milliseconds
if time.time() >= tCurrent + 1:
print "Time = %d" % time.time()
tCurrent = time.time()
La sortie est la même:
Time = 1498226796
Time = 1498226797
Time = 1498226798
Time = 1498226799
et l'utilisation du processeur est beaucoup, beaucoup plus bas:
import time
abort_after = 5 * 60
start = time.time()
while True:
delta = time.time() - start
if delta >= abort_after:
break
Je veux partager celui que j'utilise:
import time
# provide a waiting-time list:
lst = [1,2,7,4,5,6,4,3]
# set the timeout limit
timeLimit = 4
for i in lst:
timeCheck = time.time()
while True:
time.sleep(i)
if time.time() <= timeCheck + timeLimit:
print ([i,'looks ok'])
break
else:
print ([i,'too long'])
break
Ensuite, vous obtiendrez:
[1, 'looks ok']
[2, 'looks ok']
[7, 'too long']
[4, 'looks ok']
[5, 'too long']
[6, 'too long']
[4, 'looks ok']
[3, 'looks ok']