Python:"while"太慢了,实际执行时sleep(0.25)变成了sleep(3)

Python: "while" is too slow, and sleep(0.25) becomes sleep(3) in actual execution

我是 运行 Python Raspberry Pi 3 上的程序,我想每 0.25 秒从 DS18B20 传感器记录一次温度。

早些时候,当程序很简单并在 shell 上显示温度时,它非常快并且没有问题。不幸的是,由于程序本身现在包括记录到一个文件,我每 2 秒或 3 秒就会收到一个日志。

如何确保 0.25 秒的记录间隔。

我已经分享了下面的代码:

#This program logs temperature from DS18B20 and records it
#Plots the temperature-time plot.

import os
import sys
#import matplotlib.pyplot as plt
from re import findall
from time import sleep, strftime, time
from datetime import *

#plt.ion()
#x = []
#y = []

ds18b20 = ''

def setup():
    global ds18b20
    for i in os.listdir('/sys/bus/w1/devices'):
        if i != 'w1_bus_master1':
            ds18b20 = i

# Reads temperature data from the Temp sensor
# This needs to be modified for use with max31855 and K-type thermocouples
def read():
#   global ds18b20
    location = '/sys/bus/w1/devices/' + ds18b20 + '/w1_slave'
    tfile = open(location)
    text = tfile.read()
    tfile.close()
    secondline = text.split("\n")[1]
    temperaturedata = secondline.split(" ")[9]
    temperature = float(temperaturedata[2:])
    temperature = temperature / 1000
    return temperature

#Loop for logging - sleep, and interrupt to be configured.
def loop():
        while True:
                if read() != None:
                        print "Current temperature : %0.3f C" % read()
                        #sleep(0.25)
                        func()

def write_temp(temperature,file_name):
        with open(file_name, 'a') as log:
                log.write("{0},{1}\n".format(datetime.now().strftime("%d-%m-%Y %H:%M:%S"),str(temperature)))

arg = sys.argv[1]
filename1 = str(arg) + "-" + datetime.now().strftime("%d-%m-%Y-%H-%M-%S")+".csv"

def func():
        temperature = read()
        #sleep(0.25)
        write_temp(temperature,filename1)
        #graph(temperature)

#For plotting graph using MatPlotLib
#Comment out this function during foundry trials to avoid system slowdown
#Check system resource usage and slowdown using TOP or HTOP

#def graph(temperature):
#        y.append(temperature)
#        x.append(time())
#        plt.clf()
#        plt.scatter(x,y)
#        plt.plot(x,y)
#        plt.draw()              

#Interrupt from command-line
def destroy():
    pass

if __name__ == '__main__':
    try:
        setup()
        func()
        loop()
    except KeyboardInterrupt:
        destroy()

我已经注释掉了我认为占用大量资源的部分,但我仍然无法管理少于 2 秒的任何内容。我得到的结果如下:

输出:

27-09-2016 12:18:41,23.0
27-09-2016 12:18:43,23.062
27-09-2016 12:18:46,23.125
27-09-2016 12:18:48,23.187
27-09-2016 12:18:50,23.187
27-09-2016 12:18:53,23.562
27-09-2016 12:18:55,25.875
27-09-2016 12:18:58,27.187
27-09-2016 12:19:00,27.5
  1. 只打开一次日志文件(并在程序退出时将其关闭)
  2. 不要总是重新读取传感器的温度。你打电话给 read() 太频繁了。
  3. 减少一般开销并简化您的调用。

我无法完全测试这个,但像这样的东西可以工作:

import os
import sys
import time
from datetime import datetime

def read_temp(dev):
    '''Reads temperature from sensor and returns it as float.'''
    loc = '/sys/bus/w1/devices/' + dev + '/w1_slave'
    with open(loc) as tf:
        return float(tf.read().split('\n')[1].split(' ')[9][2:]) / 1000.0

def write_temp(t, logfile):
    '''Writes temperature as .3 float to open file handle.'''
    logfile.write('{0},{1:.3f}\n'.format(datetime.now().strftime('%d-%m-%Y %H:%M:%S'), t))

def loop(dev, logfile):
    '''Starts temperature logging until user interrupts.'''
    while True:
        t = read_temp(dev)
        if t:
            write_temp(t, logfile)
            print('Current temperature: {0:.3f} °C'.format(t))
            sys.stdout.flush() # Flush. Btw, print is time-consuming!
            time.sleep(.25)

if __name__ == '__main__':
    # Take the first match for a device that is not 'w1_bus_master1'
    dev = [d for d in os.listdir('/sys/bus/w1/devices') if d != 'w1_bus_master1'][0]
    # Prepare the log filename
    fname = str(sys.argv[1]) + "-" + datetime.now().strftime("%d-%m-%Y-%H-%M-%S")+".csv"
    # Immediately open the log in append mode and do not close it!
    logfile = open(fname, 'a')

    try:
        # Only pass device and file handle, not the file name.
        loop(dev, logfile)
    except KeyboardInterrupt:
        # Close log file on exit
        logfile.close()