auch autoren machen fehler!

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Gast

Dienstag 30. Dezember 2003, 14:46

hallo zusammen!

im neuen buch "objetkorientierte programmierung" von m. weigand ist ein chat zu finden. die funktionsweise läßt allerdings insofern zu wünschen übrig, als dass jeder teilnehmer die seite manuell reloaden muss um zu sehen was sein gegenüber geschrieben hat. hier der code ergänzt durch einen try und except um fehlermeldung vom server zu bekommen. ich musste auf meinem webserver den code von weigand ändern. open statt file, da der python interpreter dort file offensichtlich nicht kennt. für uns hier also interessant, was sich im try block abspielt

Code: Alles auswählen

#!/usr/bin/python

import cgi, traceback, sys

try:
    class Dialog:
        def __init__(self, datei):
            self.datei=datei
            try:
                f=open(datei, 'r')
                self.textzeilen=f.readlines()
                f.close()
            except:
                self.textzeilen=[]
                f=open(datei, 'w')
                f.close()
                
        def aktualisiere(self, nick, beitrag):
            #Neuen Beitrag in Dialog einfuegen
            if len(self.textzeilen)>10:
                self.textzeilen=self.textzeilen[-10:]
            neueZeile=nick + ': ' + beitrag + '<br>\n'
            self.textzeilen.append(neueZeile)
            f=open(self.datei, 'w')
            for z in self.textzeilen:
                f.write(z)
            f.close()
            
        def __str__(self):
            #liefert Darstellung des Dialogs als HTML-Text
            dialog=''
            for z in self.textzeilen:
                dialog+=z
            return dialog

    class Chatraum:
        def __init__(self):
            self.form=cgi.FieldStorage()
            self.dialog=Dialog('/var/www/web188/html/crossover_python/dialog.txt')
            self.beitrag=self.form.getvalue('beitrag')
            self.nick=self.form.getvalue('nick')
            self.typ=self.form.getvalue('typ','normal')
            if self.beitrag:
                if self.typ=='fluestern':
                    text='<font size="-1" color=#9F9F9F>%s </font>'
                elif self.typ=='schreien':
                    text='<font size="+2" color=#FF0000>%s </font>'
                else:
                    text='%s'
                text=text%(self.beitrag,)
                self.dialog.aktualisiere(self.nick, text)

        def __str__(self):
            seite = '''Content-Type: text/html

    <html>
    <head><title>Python-Chat</title></head>
    <body><h1>Python-Chat</h1>
    %s <hr>
    <form action="/cgi-bin/chat_b.py" method="POST">
    <input type="hidden" name="nick" value="%s">
    Ich sage:&
    <input type="text" name="beitrag" size="40" maxlength="40">
    <input type="submit" value="OK"><br><br>
    <input type="radio" name="typ" value="normal"
    checked="checked"> normal &nbsp
    <input type="radio" name="typ" value="schreien">
    schreiend &nbsp
    <input type="radio" name="typ" value="fluestern"> fl&sternd
    </form></body></html>'''%(self.dialog,self.nick)
            return seite

    print Chatraum()
except:
    pfad='/var/www/web188/html/crossover_python/'
    dateiname='fehler.txt'
    text=pfad+dateiname
    sys.stderr=open(text, 'a')
    print traceback.print_exc(sys.exc_info()[2])
    sys.stderr.close()
nun zur eigentlichen frage: wie würdet ihr das problem mit dem reload am besten lösen?

mfg

rolgal
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Dienstag 30. Dezember 2003, 15:38

Hi Rogal,

ich würde im gesendeten html noch folgende Zeile im head-bereich einfügen:

Code: Alles auswählen

 <meta http-equiv="refresh" content="10; URL=http://www.deine-domain.de/pfad_zur_seite">
So wird die Seite alle 10 Sekunden neu geladen.


Gruß

Dookie
Gast

Dienstag 30. Dezember 2003, 17:15

hi dookie!

danke mal für den tipp, hat aber das problem, dass man immer nur 10 sekunden zeit hat etwas einzugeben.

vielleicht gibts was besseres

mfg

rolgal
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Dienstag 30. Dezember 2003, 22:28

Hi! Dann machst du halt Frames: einen IFrame, der sich immer neu läd und ein Frame zum eingeben des Textes...
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Mittwoch 31. Dezember 2003, 12:41

Ja, macht mal ne bessere version, ich kann es dann dem autor schicken wenn ihr wollt (fuer die 2. version) :)
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Gast

Donnerstag 15. Januar 2004, 18:24

hallo

theoretisch hört sich das leicht an mit dem iframe, aber praktisch gibt es da wohl einige knackpunkte bzw. ich checke es net ganz. der teil der ständig aktualisiert wird muss wohl in den iframe, aber wie soll die datei die dort geladen wird auf die variable zugreifen können.

mfg

rolgal
Gast

Freitag 23. Januar 2004, 19:58

ist die lösung so einfach, dass es dumm ist danach zu fragen?

oder

ist es doch nicht so einfach?

oder

interessiert diese thematik niemand?

mfg

rolgal
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Freitag 23. Januar 2004, 20:42

Um ehrlich zu sein: nicht so sehr interessieren trifft es bei mir eher :oops: . Aber ein Vorschlag zur Lösung: Auch der I-Frame kann ja durch ein CGI-Script gebildet werden. Und beim laden des I-Frames kannst du ja Variablen per get in der Adresse übergeben, die dann im CGI des I-Frames abrufbar sind. Und das Main Script muss halt nur in die Datein reinschreiben, damit der I-Frame in regelmäßigen Abständen daraus lesen kann...

Oder war jetzt was anderes gesucht?
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Freitag 23. Januar 2004, 20:47

rolgal hat geschrieben:ist die lösung so einfach, dass es dumm ist danach zu fragen?

oder

ist es doch nicht so einfach?

oder

interessiert diese thematik niemand?
Hmm, so einfach ist das wirklich nicht.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Gast

Sonntag 8. Februar 2004, 17:32

Hallo zusammen!

Ich glaube, dass das Problem gelöst ist. Meine Tests mit einer anderen Person haben auf jeden Fall super funktioniert.

Es braucht zwei Skripten:
Das erste in diesem Fall: chat_d.py (_d steht bei mir für Version)

Code: Alles auswählen

#!/usr/bin/python

import cgi


def eingabeseite():
        print "Content-Type: text/html"
        print
        print "<html><head><title>Python-Chat</title></head>"
        print "<body>"
        print "<iframe src='http://localhost/cgi-bin/chatinhalt.py' width='40%' height='250' name='Chatinhalt'>"
        print "</iframe>"
        print "<hr>"
        print "<form action='http://localhost/cgi-bin/chat_d.py' method='POST'>"
        print "<input type='hidden' name='nick' value='%s'>"%(nick)
        print "Ich sage:&"
        print "<input type='text' name='beitrag' size='40' maxlength='40'>"
        print "<input type='submit' value='Ok'></form>"
        print "</body></html>"
    


form=cgi.FieldStorage()
dialog='/var/www/html/crossover/dialog.txt'
nick=form.getvalue('nick')
if nick:
    beitrag=form.getvalue('beitrag')
    if beitrag:
        f=open(dialog, 'r')
        textzeilen=f.readlines()
        f.close()

        neueZeile=nick + ': ' + beitrag + '<br>\n'
        textzeilen.append(neueZeile)
        f=open(dialog, 'w')
        for z in textzeilen:
            f.write(z)
        f.close()

        eingabeseite()
    else:
        eingabeseite()
else:
    print "Location: http://localhost/crossover/chat.htm \n\n"
das zweite in diesem fall: chatinhalt.py

Code: Alles auswählen

#!/usr/bin/python

dialog='/var/www/html/crossover/dialog.txt'
f=open(dialog,'r')
textzeilen=f.readlines()
f.close()
if len(textzeilen)>10:
    textzeilen=textzeilen[-10:]
inhalt=''
for i in textzeilen:
    inhalt=inhalt+i

print "Content-Type: text/html"
print
print "<html><head>"
print "<meta http-equiv='refresh' content='1; URL=http://localhost/cgi-bin/chatinhalt.py'>"
print "</head>"
print "<body><h1>Chat</h1>"
print inhalt
print "</body></html>"
Dieses zweite Skript wird in den iframe des oberen skripts geschrieben. Das Problem war: Wie kommt das zweite Skript an die Variable Inhalt.
Die einfachste Lösung ist die oben gezeigte. (rolgal geht wegen stundenlangen sich auf den kopf hauen wohl nicht mehr in die öffentlichkeit, der anblick ist nicht zumutbar:D)

Beide Skritpen müssen im selben Verzeichnis liegen.

Diese Lösung hat zwar kein schönes OOP Design, aber es funktioniert. Überhaupt habe ich einige der Cgi-Skripten aus dem Buch "Objektorientierte Programmierung mit Pyhton" ausprobiert und musste mich jedesmal fragen, ob OOP hier nicht zum Selbstzweck dient.

Die Frage, die ich zur Diskussion stellen möchte: Sollte OOP nicht dann als Lösung zum Einsatz kommen, wenn das Problem bzw. die Zielsetzung damit leichter erreicht werden kann? Und nicht einfach immer und überall, als Standardlösung.

Konkret musste ich feststellen, dass die Beispiele Chat, Shop, Abstimmung und Zaehler aus dem genannten Buch in herkömmlicher Programmierung nicht nur angenehmer zum schreiben sind, sondern auch übersichtlicher sind.
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Dienstag 10. Februar 2004, 14:50

rolgal hat geschrieben:Diese Lösung hat zwar kein schönes OOP Design, aber es funktioniert. Überhaupt habe ich einige der Cgi-Skripten aus dem Buch "Objektorientierte Programmierung mit Pyhton" ausprobiert und musste mich jedesmal fragen, ob OOP hier nicht zum Selbstzweck dient.

Die Frage, die ich zur Diskussion stellen möchte: Sollte OOP nicht dann als Lösung zum Einsatz kommen, wenn das Problem bzw. die Zielsetzung damit leichter erreicht werden kann? Und nicht einfach immer und überall, als Standardlösung.

Konkret musste ich feststellen, dass die Beispiele Chat, Shop, Abstimmung und Zaehler aus dem genannten Buch in herkömmlicher Programmierung nicht nur angenehmer zum schreiben sind, sondern auch übersichtlicher sind.
Ja, das ist die andere Seite von OOP (typisch in Java). Erzwungenes OOP ist nur selten sinnvoll, wenn überhaupt.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Dienstag 10. Februar 2004, 15:23

ich sehe das auch so, darum verwende ich auch für Webanwendungen lieber PHP ohne OOP.
Alles mit OOP machen zu wollen sehe ich genauso falsch, wie alles mit C/C++ machen zu wollen. Für verschiedene Probleme gibt es glücklicherweise verschiedene Lösungsmöglichkeiten.
Bei Python haben wir ja auch den Vorteil, sowohl prozedural wie auch funktional oder eben objektorientiert zu programmieren.


Gruß

Dookie
Gast

Dienstag 10. Februar 2004, 15:48

hallo dookie!

die permanente bevorzugung von php gegenüber python kann ich bei webanwendungen überhaupt nicht verstehen. ich habe jetzt die üblichen anwendungen mit python erstellt, abgeleitet aus dem genannten buch, aber eben prozedural.
shop, abstimmung, gästebuch, formmailer, chat usw.

forum folgt noch.

ich kann bei der verwendung von php keinen vorteil erkennen. im gegenteil: ich muss mich mit einem fast schon perl ähnlich grauslichen sprachdesign herumärgern :lol:

dafür fällt mir eine idee bei python ein. ich möchte folgendes ausprobieren. wenn ich meinen eigenen server betreibe, dürfte es kein problem darstellen mein cgi verzeichnis zum pfad hinzuzufügen, in dem nach modulen gesucht wird.

kannst du mir an dieser stelle gleich sagen, wie man den pfad abändert? (unter linux)

bei all den genannten anwendungen gibt es nämlich sehr viel codewiederholung, - z.b muss fast immer eine datei geöffnet und gelesen werden etc, formulardaten werden ausgelesen etc.

es wäre doch sicher denkbar allgemeine funktionen in ein modul zu schreiben (webtools.py) und dieses oder teile davon in all den genannten skripten zu importieren.

denke das müsste gehen. wenn, dann wäre das urgeil.

frage: wie sieht es bei php damit aus?

was mich an php grundsätzlich, abgesehen vom design stört:
ich mag keine sprachen mit denen ich so eingeschränkt bin.

mfg

rolgal
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Dienstag 10. Februar 2004, 19:38

Hi rolgal,

so hab jetzt zum ersten mal versucht ein "cgi-script" mit python zum laufen zu bringen :)
ein Blick in die httpd.conf

Code: Alles auswählen

...
# ScriptAlias: This controls which directories contain server scripts.
# ScriptAliases are essentially the same as Aliases, except that
# documents in the realname directory are treated as applications and
# run by the server when requested rather than as documents sent to the client.
# The same rules about trailing "/" apply to ScriptAlias directives as to
# Alias.
#
ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/

#
# "/usr/lib/cgi-bin" could be changed to whatever your ScriptAliased
# CGI directory exists, if you have that configured.
#
<Directory /usr/lib/cgi-bin/>
    AllowOverride None
    Options ExecCGI
    Order allow,deny
    Allow from all
</Directory>
...
zeigte mir, daß er cgi's in /usr/lib/cgi-bin/ sucht. also habe ich ihm gleich mal ein Script

Code: Alles auswählen

#!/usr/bin/python

print "Hallo Welt!"
in das Verzeichnis gelegt und versucht es mit localhost/cgi-bin/hallo.py zu starten.
Kam auch gleich ein Servererror und der hinweis auf die error.log vom Apache. Dort bemängelte er einen malformed header from script also gleich mal gesucht wie ich nen header von Python aus formen muss, damit der nicht mehr malformed ist :)

Code: Alles auswählen

#!/usr/bin/python

print "Content-Type: text/html"
print
print "Hallo Welt!"
lief dann gleich, auch mit der Endung .py :)
so jetzt zum pfad
folgendes Script pfade.py

Code: Alles auswählen

#!/usr/bin/python

import sys

print "Content-Type: text/html"
print
print """<html>
    <head>
        <title>Pythonpfade</title>
    </head>
    <body>"""
print "        <h1>Meine Pythonpfade</h1>"
for entry in sys.path:
    print entry+"<br/>"
print "    </body>\n</html>"
spuckt nach eingabe im Browser von http://localhost/cgi-bin/pfade.py eine Seite mit den voreigestellten Pfaden aus. Ändern für den import kannst Du das wie üblich mit sys.path.append("/zusatz/pfad/")


Gruß

Dookie
Gast

Mittwoch 11. Februar 2004, 11:24

hi dookie!

das mit

Code: Alles auswählen

sys.path.append[usw]
war mir schon geläufig. doch wie füge der variablen PYTHONPATH ein Verzeichnis dauerhaft hinzu?

export PYTHONPATH=/var/www/cgi-bin/module hat mal nicht funktioniert!

folgendes funktioniert, aber ich würde mir in den dateien, in denen ich importiere die anweisung

Code: Alles auswählen

sys.path.append[usw]
gerne sparen.

das modul webtool.py:

Code: Alles auswählen

#!/usr/local/bin/python

import sys

def ausgabe():
    print "Content-Type: text/html"
    print
    print "<html>"
    print "<body>"
    print sys.path
    print "</body>"
    print "</html>"

if __name__ == "__main__":
    ausgabe()
die testdatei testmodule.py:

Code: Alles auswählen

#!/usr/local/bin/python

import sys
sys.path.append('/var/www/cgi-bin/module') #da muss es doch was besseres geben, oder?

from webtool import *

ausgabe()
mfg rolgal
Antworten