Insgesamt sieht es schon besser aus, aber einige Dinge finde ich immer noch nicht so glücklich. Du solltest bei der Funktion ``transfer_received_data`` besser auf die
Command Query Separation achten. Wieso gibt die Funktion einen Booleschen Wert zurück? *transfer* ist doch eine Anweisung und deutet nicht darauf hin, dass da etwas zurück kommt. Zudem ist so ein Stil imho zu C-esque... in Python (und anderen ausdrucksstärkeren Sprachen als C) gibt es das Konzept der Exceptions, wenn wirklich etwas innerhalb so einer Funktion schief laufen sollte - da braucht man keinen Status-Rückgabewert, den Du letztlich implementiert hast.
Ich mag mich irren, aber für folgendes
Code: Alles auswählen
urltoopen = "{0}?r={1}&key={2}{3}".format(URL, RID, KEY, received_data)
bietet ``urllib`` iirc eine Methode an, bei der die Parameter einer URL gesammelt und dann automatisch korrekt an die URL hinzugefügt werden; inkl. der notwendigen Kodierungen von Sonderzeichen. Diese solltest Du imho auch nutzen. Der Name liest sich imho auch mit Underscores besser: ``url_to_open``. Ich würde die Generierung vermutlich sogar in einer Factory-Funktion "verstecken" und nicht "nackt" in der Funktion ``transfer_received_data`` stehen lassen. Wo ich so drüber nachdenke, würde ich das daraus sogar komplett entfernen und die *vollständige* URL an die Funktion übergeben:
Code: Alles auswählen
transfer_received_data(received_data, previous_received_data, build_url(RID, KEY))
Auf das wesentlich elegantere ``requests``-Modul hatten wir dich schon hingewiesen?
Für das Logging solltest Du Dir im nächsten Schritt wirklich mal das
logging-Modul angucken.
Generell solltest Du Dir die Frage stellen, *wo* Du das Logging wirklich ansiedeln willst. So etwas wie das Loggen stellt quasi immer einen sogenannten
Cross Cutting Concern dar und daher muss man sich fragen, wie man den im Code unterbringt. Speziell in der Funktion ``check_received_data`` ist es imho fraglich, ob wirklich darin geloggt werden sollte, oder nicht eher dort, wo das Ergebnis "interpretiert" wird.
Code: Alles auswählen
def check_received_data(received_data):
return received_data[2].isdigit() and received_data[4] == 't'
# später
if check_received_data(...):
# mache etwas
else:
# logge den Fehler
Ich würde dazu tendieren, das Loggen immer auf einer möglichst hohen Ebene der Domäne einzubauen - sofern es nicht nur temporär zur Fehlersuche dient. Damit kann man Funktionen leichter wiederverwenden; denn nicht in allen Szenarien muss das Loggen gefragt sein.
Du solltest auf jeden Fall den Code auf Modulebene verschwinden lassen und hinter folgendem Pattern verbergen:
Code: Alles auswählen
def main():
# hier alles, was zuvor auf Modulebene stand
serialcom = serial.Serial('/dev/ttyACM0', 9600)
serialdata_previous = ""
for line in serialcom:
serialdata = format_received_data(line)
...
if __name__ == "__main__":
main()
Damit kannst Du Dein Modul auch in anderen Modulen importieren und Funktionen daraus nutzen, *ohne* dass Code ausgeführt wird.
Dies ist in Python so üblich und gebräuchlich, dass es sich lohnt, ein Template in seinem Editor zu erstellen, welches dieses beim Erstellen einer neuen, "leeren" Python-Datei gleich mit einbaut.