2012-11-02 3 views
5

Ich lese serielle Daten mit einer While-Schleife. Ich habe jedoch keine Kontrolle über die Abtastrate.Wie stelle ich sicher, dass eine Python-While-Schleife eine gewisse Zeit benötigt, um ausgeführt zu werden?

Der Code selbst scheint 0,2 Sekunden zu laufen, also weiß ich, dass ich nicht schneller gehen kann. Aber ich möchte genau kontrollieren können, wie viel langsamer ich probe.

Ich fühle mich wie ich es mit 'Schlaf' tun könnte, aber das Problem ist, dass es Potenzial gibt, dass an verschiedenen Punkten die Schleife selbst länger dauern wird (abhängig von genau was über serielle Daten übertragen wird) Der Code müsste das Gleichgewicht ausgleichen.

Zum Beispiel möchte ich sagen, ich möchte alle 1s probieren, und die Schleife dauert zwischen 0,2s und 0,3s zu laufen. Mein Code muss intelligent genug sein, um für 0,8 Sekunden (wenn die Schleife 0,2 Sekunden dauert) oder 0,7 Sekunden (wenn die Schleife 0,3 Sekunden dauert) zu schlafen.

import serial 
import csv 
import time 

#open serial stream 
    while True: 

     #read and print a line 
     sample_value=ser.readline() 
     sample_time=time.time()-zero 
     sample_line=str(sample_time)+','+str(sample_value) 
     outfile.write(sample_line) 
     print 'time: ',sample_time,', value: ',sample_value 
+0

Ich habe diese Art von Sache vor der Verwendung von/dev/rtc als Auslöser in einem asynchronen Reaktor getan. Es löst in präzisen Intervallen unabhängig von der Messzeit aus. Du könntest aber auch einfach itimer benutzen. – Keith

Antwort

8

messen Sie einfach die Zeit, um Ihr Code ausgeführt nimmt jede Iteration der Schleife, und sleep entsprechend:

import time 

while True: 
    now = time.time()   # get the time 
    do_something()    # do your stuff 
    elapsed = time.time() - now # how long was it running? 
    time.sleep(1.-elapsed)  # sleep accordingly so the full iteration takes 1 second 

Natürlich nicht zu 100% perfekt (vielleicht aus einer Millisekunde oder eine andere von Zeit zu Zeit) aber ich denke, es ist gut genug.

from twisted.internet import task 
from twisted.internet import reactor 

def do_something(): 
    pass # do your work here 

task.LoopingCall(do_something).start(1.0) 
reactor.run() 
1

Am Anfang der Schleife überprüfen, ob die entsprechende Zeit verstrichen ist. Wenn nicht, continue.

# Set up initial conditions for sample_time outside the loop 
sample_period = ??? 
next_min_time = 0 
while True: 
    sample_time=time.time()-zero 
    if sample_time < next_min_time: 
     continue 
    #read and print a line 
    sample_value=ser.readline() 
    sample_line=str(sample_time)+','+str(sample_value) 
    outfile.write(sample_line) 
    print 'time: ',sample_time,', value: ',sample_value 
    next_min_time = sample_time + sample_period 
+2

Sie füllen die Wartezeit mit einer leeren Schleife. Verwenden Sie stattdessen 'time.sleep()', damit der Scheduler die Wartezeit mit der Verarbeitung anderer Threads/Prozesse füllen kann. –

1

Ein eher elegante Methode basiert auf UNIX Sie arbeiten: Verwenden Sie die Signalbibliothek

Der Code:


Ein weiterer netter Ansatz twisted ‚s LoopingCall verwendet

import signal 


def _handle_timeout(): 
    print "timeout hit" # Do nothing here 

def second(count): 
    signal.signal(signal.SIGALRM, _handle_timeout) 
    signal.alarm(1) 
    try: 
     count += 1 # put your function here 
     signal.pause() 

    finally: 
     signal.alarm(0) 
     return count 


if __name__ == '__main__': 

    count = 0 
    count = second(count) 
    count = second(count) 
    count = second(count) 
    count = second(count) 
    count = second(count) 

    print count 

Und das Timing:

[email protected]:~/Bureau$ time python timer.py 
5 

real 0m5.081s 
user 0m0.068s 
sys 0m0.004s 

Zwei Vorbehalte: Es funktioniert nur auf * nix, und es ist nicht multithread-sicher.

Verwandte Themen