if bedingung in cgi script; lighttpd

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
py_furby2014
User
Beiträge: 3
Registriert: Montag 6. Januar 2014, 19:14

Hallo Leute,
ich komme mit einer einfachen if Bedingung in einem cgi script nicht klar. Im Prinzip möchte ich eine Zahl auswerten und je nach Ergebnis eine Variable modifizieren.

Mein script sieht folgendermassen aus:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Debug errors on browser
import cgitb; cgitb.enable()

import sys
import os
import subprocess
from time import *

# Zeitvariable definieren
lt = localtime()

# Variablen definieren
uhrzeit = strftime("%H:%M:%S")

# py_temp Textdatei oeffnen, auslesen und wieder schliessen
file = open('py_temp.txt')
py_temp_data = file.readlines()
file.close()

print 'Content-type: text/html\n\n'
print '<html>'

print '<style>'
print '  p {'
print '    color: black;'
print '    font-size: 24px;'
print '    font-weight: bold;'
print '  }'
print '  .normal {'
print '    color: black;'
print '  }'
print '  .hot {'
print '    color: red;'
print '  }'
print '  .cold {'
print '    color: blue;'
print '  }'
print '</style>'

print '<body>'
print '<p class="normal">aktuelle Uhrzeit: ' + uhrzeit + '</p>'
print '<hr style="color:#ceb98e ; height:2px "/>'

# Fuer jede Zeile eine Ausgabe
for line in py_temp_data:
  py_temp_data = line.split("\n")[0]
  split_py_temp = py_temp_data.split('*', 1)
  output_py_temp = split_py_temp[1]

#  line_color = "normal"

# Die Temperatur kalkulieren
  split_calc_temp = output_py_temp.split(': ', 1)
  calc_temp = split_calc_temp[1]

  if calc_temp >= 22.0 :
    line_color = "hot"
  elif calc_temp <= 19.0 :
    line_color = "cold"
  else:
    line_color = "normal"
    break

# Ausgabe der aktuellen Temperatur
  print '<p class="' + line_color + '">  ' + output_py_temp + ' Grad</p>'

print '<hr style="color:#ceb98e ; height:2px "/>'

print '</body></html>'

sys.exit(0)
Es geht um eine Zahl die als calc_temp gespeichert ist und je nach Ergebnis soll Variable line_color gesetzt werden. Aber irgendwie klappt das nicht. line_color ist bei mir immer 'hot' - also immer das Ergebnis der ersten if bedingugen, das ist aber nicht korrekt. Das cgi script läuft dabei als user www-data im Verzeichnis: /var/www/cgi-bin/ und im Prinzip funtioniert es soweit, es werden keine Fehler angezeigt.

Was mache ich nur falsch?
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@py_furby2014: Das ist eine Unschönheit von Python2: dort sind Strings grundsätzlich größer als jede Zahl.

Zum Skript: außer »time« wird kein einziger Import gebraucht. Und der ist auch noch ein '*'-import, den Du vermeiden solltest, weil Du nicht kontrollieren kannst, was in Deinen Namensraum importiert wird. Das »sys.exit(0)« zum Schluß ist überflüssig.
Du solltest Dir überlegen für Dein HTML irgendeine Form von Templates zu benutzen. Dieses Mischen von Ausgabe und Berechnung macht das ganze Skript total unübersichtlich.
BlackJack

@py_furby2014: Du vergleichst eine Zeichenkette mit einer Zahl. Du möchtest die Zeichenkette vorher in eine Zahl umwandeln, damit da ein sinnvoller Vergleich zustande kommt.

Das ``sys.exit(0)`` am Ende ist überflüssig.

Edit:
@Sirius3: <korinthenkacker>In Python 2 sind Zeichenketten entweder grösser oder kleiner als Zahlen. Welches davon ist nicht garantiert, nur dass es während eines Programmlaufes gleich bleibt. Das heisst es kann sich pro Lauf auch ändern. Das ist zumindest was die Sprachdefinition maximal garantiert. :-)</korinthenkacker>
py_furby2014
User
Beiträge: 3
Registriert: Montag 6. Januar 2014, 19:14

OK. Ich denke ich habe verstanden was ihr meint.

Stehe halt noch ganz am Anfang, bzgl. Python-Programmierung und werde versuchen mein script zu verbessern.

Das cgi script wertet ein einfaches txt file aus, welches von meinem RaspPi (Temperaturmessung) geliefert wird. Die Temperatur wird dabei von einem bereits funktionierendem Pythonscript geliefert. Ich denke, ich werde da bereits ansetzen um das eigenliche cgi script zu vereinfachen.

DANKE
BlackJack

@py_furby2014: Noch ein paar Anmerkungen: Der Style Guide for Python Code empfiehlt vier Leerzeichen pro Einrückebene.

Kommentare sollten dem Leser einen Mehrwert liefern und nicht einfach noch mal das offensichtliche wiederholen was schon im Quelltext steht. Faustregel: Quelltext so schreiben das er selbsterklärend ist, und Kommentare nutzen wenn nicht so leicht klar ist *warum* der Code etwas so macht wie er es macht. Denn *was* er macht steht ja schon im Code selbst.

Abkürzungen bei Namen vermeiden sofern die Abkürzung nicht allgemein bekannt ist. Namen sollen Klarheit schaffen und nicht zum Rätselraten zwingen. ;-)

Auch wenn `_temp` ein üblicher Namenszusatz für temporäre Werte ist, wird das in Programmen die mit *Temp*eraturen arbeiten, schnell man verwirrend.

Dem Namen `lt` wird ein Wert zugewiesen, dann wird er aber nirgends mehr verwendet.

`file` ist der Name eines eingebauten Datentyps, den sollte man nicht an etwas anderes binden. Die Datei braucht man auch nicht komplett einlesen sondern kann direkt über das offene Dateiobjekt iterieren. Das macht hier zum Beispiel auch Sinn, weil bei der ersten „normalen” Temperatur die Verarbeitung ja abgebrochen wird, die Datei also gar nicht bis zum Ende gelesen werden muss wenn das passiert. Wobei ich mich frage ob das wirklich so sein soll?

Dateien sollte man mit der ``with``-Anweisung zusammen öffnen. Dann ist sichergestellt, dass sie auch in jedem Fall wieder geschlossen werden.

Das die Schleife über die Elemente von `py_temp_data` iteriert und den selben Namen *in* der Schleife für andere Werte verwendet ist verwirrend.

``line.split("\n")[0]`` ist ein umständlicher und verschleiernder Weg um das Zeichen am Ende der Zeile zu entfernen. Hier wäre ``strip()`` oder ``rstrip()`` üblich. Man kann das auch wieder an `line` binden, denn letztendlich repräsentiert der Wert immer noch die Zeile. Letztendlich ist das entfernen nicht nötig weil es bei einer Umwandlung in eine Zahl nicht stört.

Zeichenketten und Werte mit ``+`` zusammen zu setzen ist eher BASIC als Python. In Python gibt es dafür Zeichenkettenformatierung.

Ich komme ungefähr bei so etwas heraus (ungetestet):

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import cgitb
cgitb.enable()
from string import Template
from time import strftime

RESPONSE_TEMPLATE = Template('''\
Content-type: text/html\n\n
<html><head>
<title></title>
<style>
  p {
    color: black;
    font-size: 24px;
    font-weight: bold;
  }
  .normal {
    color: black;
  }
  .hot {
    color: red;
  }
  .cold {
    color: blue;
  }
  hr {
    color:#ceb98e;
    height:2px;
  }
</style></head>
<body>
  <p class="normal">aktuelle Uhrzeit: $uhrzeit</p>
  <hr>
  $temperatures
  <hr>
</body></html>
''')


def main():
    temperature_paragraphs = list()
    with open('py_temp.txt') as lines:
        for line in lines:
            _, output_text = line.split('*', 1)
            _, temperature_text = output_text.split(':')
            temperature = float(temperature_text)
            if temperature >= 22.0:
                line_color = 'hot'
            elif temperature <= 19.0:
                line_color = 'cold'
            else:
                line_color = 'normal'
                break  # TODO Really? Then the assignment above makes no sense.
            temperature_paragraphs.append(
                '<p class="{0}">  {1} Grad</p>'.format(line_color, output_text)
            )
    print RESPONSE_TEMPLATE.substitute(
        temperatures='\n'.join(temperature_paragraphs),
        uhrzeit=strftime('%H:%M:%S')
    )


if __name__ == '__main__':
    main()
Du solltest Dir aber trotzdem mal eine HTML-Templating-Engine wie Jinja2 ansehen, und statt CGI ein Rahmenwerk. Hierfür tut es auch ein Mikrorahmenwert wie Bottle oder Flask.
py_furby2014
User
Beiträge: 3
Registriert: Montag 6. Januar 2014, 19:14

Hey BlackJack,
Vielen Dank fuer deine ausfuehrliche Antwort. Ich werden deinen code im Detail studieren und mit jedem Kommando sicherlich neues kennenlernen - auch der link zum StyleGuide ist sehr hilfreich. Gerade zu Beginn einer neuen Sprache kann man da sicherlich viele Fehler machen, die man dann noch tief verinnerlicht.

Bye, Bye
Antworten