@8023: Noch ein paar Anmerkungen zum Quelltext:
Python 2 ist am Ende, das sollte man nicht mehr verwenden, insbesondere nicht für neue Projekte:
https://pythonclock.org/
Eingerückt wird vier Leerzeichen pro Ebene.
Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.
Importe von mehreren Modulen kommen üblicherweise in separate Zeilen und wenn man Importe nach ”Quelle” gruppiert, sieht man leichter was aus der Standardbibliothek, was aus externen Bibliotheken, und was aus dem eigenen Projekt kommt.
Die `read_sensor()`-Funktion sollte sich weder um die Umwandlung in eine Zeichenkette noch um die Ausgabe einer Fehlermeldung kümmern. Da sind beides Aufgaben des Aufrufers.
Die Ausgabe könnte man per `logging` machen, denn dann hätte der Aufrufer die Chance sie zu unterdrücken und/oder zu entscheiden wie und wo sie erfolgen soll.
Dateien sollte man wo möglich zusammen mit der ``with``-Anweisung öffnen um das schliessen auch ohne ``try``/``finally`` sicherzustellen.
Bei Textdateien sollte man immer explizit eine Kodierung angeben.
Die `readline()`-Methode von Dateien braucht man nur sehr selten tatsächlich und sie ist ineffizienter als das Dateiobjekt als Iterator über Zeilen zu verwenden.
Pfade/Dateinamen und die regulären Ausdrücke würde ich als Konstanten herausziehen.
Einbuchstabe Namen sind nur sehr selten gute Namen. `file` und `match` sollte man ausschreiben.
Zusammenstückeln von Werten und Zeichenkettenliteralen per `str()` und ``+`` ist eher BASIC als Python. Wiederholtes ``+=`` ist zudem ineffizient weil Zeichenketten unveränderbar sind, und dadruch jedes mal mehr Daten in eine neue Zeichenkette kopiert werden müssen. In Python gibt es für so etwas Zeichenkettenformatierung mit der `format()`-Methode und ab Python 3.6 f-Zeichenkettenliterale.
Ungetestet:
Code: Alles auswählen
#!/usr/bin/env python3
import logging
import re
import subprocess
import rrdtool
LOGGER = logging.Logger(__name__)
SENSOR_FILENAME = '/sys/bus/w1/devices/28-00044a52d2ff/w1_slave'
RRD_FILENAME = '/home/pi/bosch.rrd'
SHELLY_FILENAME = 'shelly.sh'
HEX_VALUE_PATTERN = '(?:[0-9a-f]{2} ){9}'
CRC_RE = re.compile(HEX_VALUE_PATTERN + ': crc=[0-9a-f]{2} YES')
VALUE_RE = re.compile(HEX_VALUE_PATTERN + 't=(?P<value>[+-]?[0-9]+)')
def read_sensor(path):
try:
with open(path, 'r', encoding='ASCII') as lines:
if CRC_RE.match(next(lines)):
match = VALUE_RE.match(next(lines))
if match:
return int(match.group('value')) / 1000
except IOError:
LOGGER.exception('Error reading %s', path)
return None
def main():
value = read_sensor(SENSOR_FILENAME)
shelly_result = subprocess.run(
SHELLY_FILENAME,
check=True,
stdout=subprocess.PIPE,
universal_newlines=True,
)
data = f'N:{"U" if value is None else value}:{shelly_result.stdout}'
rrdtool.update(RRD_FILENAME, data)
print('RRD data:', data)
if __name__ == '__main__':
main()