Kommandos filtern (regex?)

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
HeAdLeSs
User
Beiträge: 22
Registriert: Dienstag 8. März 2016, 09:22

Hallo zusammen.

Ich bin noch recht neu in Python und bräuchte mal einen Lösungsansatz.

Ich bin dabei eine Funktion zu schreiben an die ich ein Kommando übergeben möchte. Diese Kommandos/Eingaben müssen dann von der Funktion erkannt und ausgewertet werden. Dazu können Parameter in dem String variieren.

Als Beispiel:
Ich habe eine Kommandoliste die meine Funktion kennt. Sagen wir 'How are you?', 'status', 'make 1 picture', ...
Aktuell erkenne ich die Kommandos mit einer IF Abfrage.

Code: Alles auswählen

    command = str(sms['TextDecoded']).lower()
    if command == "how are you?":
        sms_send_sms(sms['SenderNumber'], bob.bob_say_hello())
    elif command == "status":
        sms_send_sms(sms['SenderNumber'], bob.bob_status())
    elif command == "make 1 picture":
        file = pi_camera.make_picture_camera1(mysql, cursor, config, 0, 0, 0, 1)
        sms_send_sms(sms['SenderNumber'], "I made 1 picture. File name: %s" % file)
    else:
        return false
Meine beiden Fragen. Kann man soetwas besser Lösen als mit einer IF Abfrage.
Und die wichtigere Frage: Wie kann ich 'make 1 picture' parsen... so das ich auch als Kommando 'make 3 pictures' eingeben kann und die Anzahl der Bilder parsen kann. Ich für spontan auf regex tippen. Aber wie? Und gibt es vielleicht eine andere Lösung als regex.

Dank für eure Hilfe.

Viele Grüße
HeAdLeSs
Sirius3
User
Beiträge: 18255
Registriert: Sonntag 21. Oktober 2012, 17:20

@HeAdLeSs: Du solltest entweder in allen oder gar keinem if-Zweig etwas zurückgeben und nicht nur im letzten. Welchen Typ hat sms['TextDecoded']? Macht es da Sinn, den in einen String umzuwandeln? Du solltest Dich an DRY (don't repeat yourself) halten.
Ein regulärer Ausdruck wäre z.B.:

Code: Alles auswählen

if regex.match("^make \d+ pictures?$", command):
    ...
HeAdLeSs
User
Beiträge: 22
Registriert: Dienstag 8. März 2016, 09:22

Hallo Sirius3. Du hast recht, da müssen noch die returns rein.
Welchen Typ sms['TextDecoded'] hat kann ich spontan gar nicht sagen. Es kommt aus der Datenbank und müsste eigentlich ein String sein. Weiß ich aber gerade nicht genau.

Danke für den Code. Wie kriege ich die Zahl da raus? Muss ich danach noch mal einen regex ausführen (siehe unten) oder kann ich den regex aus dem if schon irgendwie nutzen?

Code: Alles auswählen

command = str(sms['TextDecoded']).lower()
    if command == "how are you?":
        return sms_send_sms(sms['SenderNumber'], bob.bob_say_hello())
    elif command == "status":
        return sms_send_sms(sms['SenderNumber'], bob.bob_status())
    elif regex.match("^make \d+ pictures?$", command):
        reg = regex.match("^make \d+ pictures?$", command)
        file = pi_camera.make_picture_camera1(mysql, cursor, config, 0, 0, 0, reg.group(0))
        return sms_send_sms(sms['SenderNumber'], "I made 1 picture. File name: %s" % file)
    else:
        return false
BlackJack

@HeAdLeSs: Kannst Du die Kommandos nicht etwas sauberer entwerfen so das die alle einem Muster folgen? Also zum Beispiel das die alle mit dem Kommando anfangen das durch ein Leerzeichen von eventuellen Argumenten getrennt ist‽ Dann könnte man dieses erste Wort abtrennen und für jedes Kommando eine eigene Funktion schreiben die dann den Rest der Argumente verarbeitet und hätte schon mal nicht alles in einer Funktion.

Wie ist denn `false` definiert? Oder sollte das `False` heissen? Und muss die Funktion überhaupt irgend etwas zurückgeben? Was bedeutet das denn?
HeAdLeSs
User
Beiträge: 22
Registriert: Dienstag 8. März 2016, 09:22

@BlackJack
Spontan würde ich sagen ja. Müsste ich die Struktur der Befehle zwar etwas umfrickeln, im Prinzip könnte ich es aber so machen. Positiv ist auch das ich ja noch am Anfang bin und kaum Befehle existieren.
Danke für den Denkansatz. Finde ich interessant. Wie würde man das Realisieren? Besonders den Functionsaufruf.

Der Hintergrund der Geschichte ist ein Befehlsverarbeiter für einen Pi, der mal irgendwelche Homeautomatisation Aufgaben erledigen soll. Dazu muss er ja meine Befehle erkennen und verarbeiten können :)

Sorry, sollte natürlich 'False' heißen.
Ja, einen Rückgabewert brauche ich damit ich weiß ob er den Befehl erkannt hat und der Task erfolgreich ausgeführt wurde.
HeAdLeSs
User
Beiträge: 22
Registriert: Dienstag 8. März 2016, 09:22

So, habe jetzt nachgeschaut. Es ist nur ein String und damit kann die Zeile natürlich vereinfacht werden.
command = sms['TextDecoded'].lower()
Funzt. :)

Ich habe mir das mit dem dynamischen Funktionsaufruf auch gerade mal angeschaut. Ist eine tolle Sache. Aber ich denke ich bleibe bei den IF's. Das lässt mir mehr Spielraum für 'Menschlichkeit'. "make 2 pictures" 'klingt' doch besser als 'picture 2'. Natürlich haben beide Varianten Vor- und Nachteile. Der dynamische Aufruf hingegen ist natürlich viel kürzer. Aber die ganzen Befehle muss man sich dann auch erstmal merken. Besonders wenn es mal Komplizierter wird. ("make 5 pictures with 5 sec delay" oder "make timelapse with 500 pictures and 5 sec delay and convert it" oder "switch on light in bedroom with 60%") ... Da merk ich gerade... wenn ich das jedesmal auschreiben muss... ich denke noch mal über getattr nach :D

Danke für eure Hilfe. Hat mir sehr weitergeholfen :idea:
Sirius3
User
Beiträge: 18255
Registriert: Sonntag 21. Oktober 2012, 17:20

@HeAdLeSs: wenn der Rückgabewert anzeigen soll ob der Befehl erfolgreich war, wäre es wahrscheinlich besser, dafür Exceptions zu benutzen. Bei Deinen menschlicheren Befehlen hat der Mensch die Schwierigkeit einen langen Satz exakt so zu schreiben, wie Du ihn erwartest.
HeAdLeSs
User
Beiträge: 22
Registriert: Dienstag 8. März 2016, 09:22

@Sirius3
Stimmt, mit execptions geht das auch. Ich bin da noch am Basteln und muss eh noch die Exceptions (schon zur Fehlerbehandlung) einbauen.
Hast recht. Habe mich jetzt doch für die Befehlsstruktur entschieden. Ist einfach kürzer beim Tippen. Muss ich mir nur die ganzen Befehle mit Parametern merken :K :mrgreen:
Antworten