2012-11-02 33 views
5

Tôi đang đọc dữ liệu nối tiếp với vòng lặp while. Tuy nhiên, tôi không kiểm soát được tốc độ lấy mẫu.Làm cách nào để đảm bảo rằng một vòng lặp trong Python mất một lượng thời gian cụ thể để chạy?

Bản thân mã có vẻ mất 0,2 giây để chạy, vì vậy tôi biết tôi sẽ không thể phát triển nhanh hơn thế. Nhưng tôi muốn có thể kiểm soát chính xác tôi lấy mẫu bao nhiêu.

Tôi cảm thấy mình có thể làm điều đó bằng cách sử dụng 'ngủ', nhưng vấn đề ở đây là có khả năng ở các điểm khác nhau, bản thân vòng lặp sẽ mất nhiều thời gian hơn (tùy thuộc vào chính xác những gì đang được truyền qua dữ liệu nối tiếp) mã sẽ phải bù đắp số dư.

Ví dụ: giả sử tôi muốn lấy mẫu mỗi 1 giây và vòng lặp mất từ ​​0,2 giây đến 0,3 giây để chạy. Mã của tôi cần phải đủ thông minh để ngủ cho 0.8s (nếu vòng lặp mất 0.2s) hoặc 0.7s (nếu vòng lặp mất 0.3s).

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

Tôi đã thực hiện loại điều này trước khi sử dụng/dev/rtc làm trình kích hoạt trong lò phản ứng không đồng bộ. Nó kích hoạt tại các khoảng thời gian chính xác độc lập với thời gian đo. Nhưng bạn cũng có thể sử dụng itimer. – Keith

Trả lời

8

Chỉ cần đo thời gian chạy mã của bạn mất mỗi lần lặp của vòng lặp, và sleep phù hợp:

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 

Tất nhiên là không hoàn hảo 100% (có thể tắt một phần nghìn giây này hay cách khác bất cứ lúc nào) nhưng tôi đoán là đủ rồi.


Một cách tiếp cận đẹp đang sử dụng 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() 
1

Khi bắt đầu kiểm tra vòng lặp nếu lượng thời gian thích hợp đã trôi qua. Nếu không, 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

Bạn đang lấp đầy thời gian chờ đợi bằng một vòng lặp trống. Thay vì sử dụng 'time.sleep()' để cho phép trình lập lịch biểu lấp đầy thời gian chờ đợi với việc xử lý các luồng/quy trình khác. –

1

Một phương pháp khá tao nhã là bạn đang làm việc trên UNIX: sử dụng thư viện tín hiệu

Mã:

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 

Và thời gian:

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

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

Hai điều cần lưu ý: nó chỉ hoạt động trên * nix và không an toàn đa luồng.