Probleme mit while

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
frannek
User
Beiträge: 33
Registriert: Dienstag 28. Januar 2014, 12:17

Hallo zusammen,

ich hab nun sämtliche Ideen probiert aber irgendwie komme ich einfach nicht drauf.

Ich habe einen Modbuslogger geschrieben welcher in einem Zyklus X sich daten von diversen Sensoren zieht. Das funktionierte bislang absolut ohne Probleme bis eine neue Hardware hinzu kam, welche die Regsiter zum Zeitpunkt der Messung sperrt. Mei nProgramm schreibt bislang einfach als value ein "disconnected" raus.
Nun möchte ich aber, dass im falle eines IOError (also Disconneted) das ganze nach ein paar Sekunden noch einmal probiert wird (z.B. noch drei Mal - ansonsten disconnected). Und genau da habe ich mein Problem. Da ich das bislang nur mit "while True" etc und händischer Eingabe gelernt habe, benötige ich eine kurze Hilfe:

Code: Alles auswählen

# ...
    count = 1
    os.system('echo "1" > /sys/class/gpio/gpio21/value')

    for i in instrumentlist:
        try:
            pressure_list[count] = i.read_float(register_list[count], functioncode=4)
        except IOError as ex:
            pressure_list[count] = 'disconnect'
        except ValueError as ex:
            pressure_list[count] = 'invalid'
        time.sleep(0.08) 

        count += 1


Wie kann ich es veranlassen, dass der "disconnect" erst nach z.B. drei versuchen als Wert eingetragen wird?


Würde mich freuen, wenn mir jemand ganz kurz unter die Arme greifen könnte.


Wünsche einen angenehmen Tag


Frannek
BlackJack

@frannek: Das mit dem `count` sieht unpythonisch aus. Listen mit Dummywerten erstellen um sie dann der Reihe nach über einen Index durch die tatsächlichen Werte zu ersetzen ist ein „anti pattern“ in Python. Man würde stattdesse mit einer leeren Liste beginnen und die Werte dort einfach anhängen statt einen Index führen und aktuell halten zu müssen.

`i` ist ein schlechter Name für etwas was keine ganze Zahl ist, insbesondere wenn es auch noch eine Laufvariable in einer Schleife ist. Das ist überraschend und verwirrend. Ausserdem sollte man nicht unnötig Abkürzen. Den Wert `instrument` zu nennen ist doch viel verständlicher im folgenden Code.

Die konkrete Grunddatenstruktur hat in Namen nichts verloren. Es kommt oft genug vor das der Typ im Laufe der Programmentwicklung geändert wird, entweder weil ein anderer Datentyp passender ist, oder weil man den Grunddatentyp irgendwann durch einen eigenen Typ ersetzt. Und dann hat man entweder irreführende Namen oder muss den Namen überall anpassen und auch verfolgen wo der Wert noch überall verwendet wird und ob er dort auch an nun falsche Namen gebunden wird.

Das mischen von verschiedenen (Duck-)Typen in einer Liste ist nicht wirklich schön. Man muss dann bei der Verarbeitung immer die Sonderfälle durch extra Code berücksichtigen. Mindestens das 'invalid' würde ich versuchen durch den Gleitkommawert NaN zu ersetzen.

Zum eigentlichen Problem: Du müsstest das Lesen des Wertes halt in einer Schleife setzen die maximal drei mal durchlaufen wird. Wenn keine Ausnahme aufgetreten ist, dann muss die Schleife verlassen werden, zum Beispiel durch ein ``break`` oder wenn man das in eine eigene Funktion herauszieht durch ein ``return``. Beim ``break`` kann es sinnvoll sein daran zu denken das Schleifen einen ``else``-Zweig besitzen können.

Das in den vorhandenen Code zusätzlich hinein zu basteln ist vielleicht etwas unübersichtlich. Zieh das Teilproblem *einen* Wert von *einem* Instrument zu lesen am besten in eine Funktion. (Teil)Probleme in kleinere Teilprobleme zu zerlegen ist ein wichtiger Ansatz beim Programmieren.
BlackJack

Mal ein Ansatz für so eine Funktion:

Code: Alles auswählen

# !/usr/bin/python
# coding: utf8
from __future__ import absolute_import, division, print_function
import time
from itertools import izip


def read_pressure(instrument, register, retry_count=3):
    try:
        for _ in xrange(retry_count):
            try:
                return instrument.read_float(register, functioncode=4)
            except IOError:
                pass  # Intentionally ignored.
        return 'disconnect'
    except ValueError:
        return float('nan')


def main():
    # ...
    
    with open('/sys/class/gpio/gpio21/value', 'wb') as gpio_file:
        gpio_file.write(b'1\n')

    pressure_values = [42]  # Oder was immer an Index 0 stehen soll.
    for instrument, register in izip(instruments, registers):
        pressure_values.append(read_pressure(instrument, register))
        time.sleep(0.08)
Dabei bin ich dann auch gleich das überflüssige `os.system()` losgeworden. Um einen Wert in eine Datei zu schreiben muss man echt keine externe Shell starten.
Antworten