2012-11-08 16 views

risposta

61

provare quanto segue:

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 

Si consiglia inoltre di aggiungere un breve sonno qui quindi questo ciclo non sta intasando CPU (ad esempio time.sleep(1) all'inizio o alla fine del corpo del ciclo).

+1

Grazie questo funziona :) – Adilicious

+0

Io uso 'timeit.default_timer', che è sempre l'orologio più preciso per la piattaforma. In particolare, 'time.time' ha una granularità di 1/60 s su Windows, che potrebbe non essere sufficiente se si ha un timeout molto breve. Su Python 3, ci sono anche 'time.monotonic',' time.perf_counter' e 'time.process_time', che potrebbero essere migliori (non ho affrontato nessuno di questi molto). – jpkotta

+3

Ci sono troppe condizioni da elaborare in questa soluzione. Questo dovrebbe essere ottimizzato e 'while True' sostituito con' while time.time()

3
import time 

abort_after = 5 * 60 
start = time.time() 

while True: 
    delta = time.time() - start 
    if delta >= abort_after: 
    break 
25

Prova questo modulo: 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 

saluti

+26

Knock knock - Chi è lì? - La mucca che interrompe - La mucca che interrompe - ** MOOOOO **! –

+0

hahahah =) E tutto si ferma! = P – andrefsp

+2

Questa soluzione dovrebbe essere la risposta accettata secondo me. Funziona molto meglio, cioè. molto più codice viene eseguito all'interno del ciclo durante un determinato periodo. – domoarrigato

22

Non è necessario utilizzare il ciclo while True: in questo caso. C'è un modo molto più semplice di utilizzare la condizione di tempo direttamente:

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 
+0

Perché non si menziona la probabile necessità di arrestare la CPU per essere caricata da questa funzione utilizzando una sospensione? Questo codice potrebbe funzionare, ma utilizzare inutilmente le risorse di sistema. – Anthony

+0

Anthony, puoi spiegare perché "usa inutilmente le risorse di sistema?" Sono sinceramente curioso e un po 'confuso; nessun altro al di sopra di questo usato time.sleep(). Perché inserire il controllo logico nelle risorse del sistema hog dell'istruzione while? –

+0

Un buon punto su come impostare il controllo del timeout nelle condizioni del ciclo while. Per quanto riguarda il commento su 'time.sleep()', il codice non funziona, quindi scorrerà il ciclo il più velocemente possibile. Aggiungendo un breve 'time.sleep()' la CPU può andare inattiva invece di funzionare a pieno regime senza fare nulla. – Baldrickk

2
risposta di

Petr Krampl è il migliore a mio parere, ma c'è ancora molto da dire circa la natura del loop e come ottimizzare l'utilizzo del sistema . I principianti che si trovano su questo thread possono essere ulteriormente confusi dagli errori logici e algoritmici nella domanda e dalle risposte esistenti.

In primo luogo, diamo un'occhiata a ciò che il codice fa, come è stato originariamente scritto che:

while True: 
    test = 0 
    if test == 5: 
     break 
    test = test - 1 

Se si dice while True in un contesto ciclo, di solito la vostra intenzione è di rimanere nel ciclo per sempre. Se questa non è la tua intenzione, dovresti prendere in considerazione altre opzioni per la struttura del ciclo. Petr Krampl ti ha mostrato un modo perfettamente ragionevole per gestirlo, che è molto più chiaro a qualcun altro che potrebbe leggere il tuo codice. Inoltre, ti sarà più chiaro qualche mese più tardi nel caso in cui avessi bisogno di rivisitare il tuo codice per aggiungere o correggere qualcosa. Il codice ben scritto fa parte della tua documentazione. Di solito ci sono diversi modi di fare le cose, ma questo non rende tutti i metodi ugualmente validi in tutti i contesti. while true è un buon esempio di questo specialmente in questo contesto.

Successivamente, esamineremo l'errore algoritmico nel codice originale. La prima cosa che fai nel loop è assegnare da 0 a test. La prossima cosa che fai è verificare se il valore di test è 5, il che non sarà mai il caso, a meno che tu non abbia più thread che modificano la stessa posizione di memoria. Il threading non rientra nell'ambito di questa discussione, ma vale la pena notare che il codice potrebbe funzionare tecnicamente, ma anche con più thread mancherebbe molto, ad es. semafori. Ad ogni modo, ti troverai in questo ciclo per sempre a prescindere dal fatto che la sentinella stia forzando un ciclo infinito.

La dichiarazione test = test - 1 è inutile indipendentemente da ciò che fa perché la variabile viene reimpostata all'inizio della successiva iterazione del ciclo. Anche se lo hai modificato in test = 5, il ciclo sarebbe ancora infinito perché il valore viene reimpostato ogni volta. Se sposti l'istruzione di inizializzazione al di fuori del ciclo, allora avrà almeno la possibilità di uscire. Quello che si può avere inteso era qualcosa di simile:

test = 0 
while True: 
    test = test - 1 
    if test == 5: 
     break 

L'ordine delle istruzioni del ciclo dipende dalla logica del programma.Funzionerà in qualsiasi ordine, però, che è il punto principale.

Il prossimo numero è il probabile e probabile errore logico di iniziare da 0, sottraendo continuamente 1 e quindi confrontandolo con un numero positivo. Sì, ci sono occasioni in cui questo potrebbe effettivamente essere ciò che intendi fare purché tu capisca le implicazioni, ma questo probabilmente non è ciò che intendevi. Le versioni più recenti di python non si avvolgeranno quando si raggiunge il "fondo" dell'intervallo di un intero come C e vari altri linguaggi. Ti consentirà di continuare a sottrarre 1 finché non avrai riempito la memoria disponibile sul tuo sistema o almeno ciò che è stato assegnato al tuo processo. Guarda il seguente script ed i risultati:

test = 0 

while True: 
    test -= 1 

    if test % 100 == 0: 
     print "Test = %d" % test 

    if test == 5: 
     print "Test = 5" 
     break 

che produce questo:

Test = -100 
Test = -200 
Test = -300 
Test = -400 
... 
Test = -21559000 
Test = -21559100 
Test = -21559200 
Test = -21559300 
... 

Il valore di test non sarà mai 5, in modo da questo ciclo non sarà mai uscita.

Per aggiungere alla risposta di Petr Krampl, Ecco una versione che è probabilmente più vicino a quello che effettivamente inteso in aggiunta a uscire dal ciclo dopo un certo periodo di tempo:

import time 

test = 0 
timeout = 300 # [seconds] 

timeout_start = time.time() 

while time.time() < timeout_start + timeout: 
    if test == 5: 
     break 
    test -= 1 

E ancora non si rompe sulla base di il valore di test, ma questo è un ciclo perfettamente valido con una condizione iniziale ragionevole. Un ulteriore controllo dei limiti potrebbe aiutarti a evitare l'esecuzione di un ciclo molto lungo senza motivo, ad es. controlla se il valore del test è inferiore a 5 all'entrata del ciclo, il che interromperebbe immediatamente il ciclo.


Un'altra cosa da dire che nessun'altra risposta è stata presa in considerazione. A volte quando si esegue un loop in questo modo, è possibile che non si desideri consumare la CPU per tutto il tempo assegnato. Ad esempio, supponi di controllare il valore di qualcosa che cambia ogni secondo. Se non si introduce una sorta di ritardo, si utilizzerà ogni ciclo disponibile della CPU assegnato al processo. Va bene se è necessario, ma un buon design permetterà a molti programmi di funzionare in parallelo sul tuo sistema senza sovraccaricare le risorse disponibili. Una semplice istruzione del sonno libererà la maggior parte dei cicli della CPU assegnati al processo in modo che altri programmi possano funzionare.

L'esempio seguente non è molto utile, ma dimostra il concetto. Diciamo che vuoi stampare qualcosa ogni secondo. Un modo per farlo sarebbe come questo:

import time 

tCurrent = time.time() 

while True: 
    if time.time() >= tCurrent + 1: 
     print "Time = %d" % time.time() 
     tCurrent = time.time() 

L'uscita sarebbe questo:

Time = 1498226796 
Time = 1498226797 
Time = 1498226798 
Time = 1498226799 

E l'utilizzo della CPU processo sarebbe simile a questa:

enter image description here

Ecco una quantità enorme di utilizzo della CPU per fare praticamente nessun lavoro.Questo codice è più comodo il resto del sistema:

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() 

L'uscita è la stessa:

Time = 1498226796 
Time = 1498226797 
Time = 1498226798 
Time = 1498226799 

e l'utilizzo della CPU è molto, molto inferiore:

enter image description here

0

Voglio condividere quello che sto usando:

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 

quindi si otterrà:

[1, 'looks ok'] 
[2, 'looks ok'] 
[7, 'too long'] 
[4, 'looks ok'] 
[5, 'too long'] 
[6, 'too long'] 
[4, 'looks ok'] 
[3, 'looks ok'] 
Problemi correlati