How do I ensure that a Python while-loop takes a particular amount of time to run?

后端 未结 3 1407
南旧
南旧 2021-01-01 03:37

I\'m reading serial data with a while loop. However, I have no control over the sample rate.

The code itself seems to take 0.2s to run, so I know I won\'t be able to

相关标签:
3条回答
  • 2021-01-01 04:01

    At the beginning of the loop check if the appropriate amount of time has passed. If it has not, sleep.

    # 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:
            time.sleep(next_min_time - sample_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: {}, value: {}'.format(sample_time, sample_value)
        next_min_time = sample_time + sample_period
    
    0 讨论(0)
  • 2021-01-01 04:02

    Just measure the time running your code takes every iteration of the loop, and sleep accordingly:

    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
    

    Of course not 100% perfect (maybe off one millisecond or another from time to time), but I guess it's good enough.


    Another nice approach is using twisted's LoopingCall:

    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()
    
    0 讨论(0)
  • 2021-01-01 04:08

    An rather elegant method is you're working on UNIX : use the signal library

    The code :

    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
    

    And the timing :

     georgesl@cleese:~/Bureau$ time python timer.py
     5
    
     real   0m5.081s
     user   0m0.068s
     sys    0m0.004s
    

    Two caveats though : it only works on *nix, and it is not multithread-safe.

    0 讨论(0)
提交回复
热议问题