allgemeine probleme bei der erstellung einer web app

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Costi
User
Beiträge: 544
Registriert: Donnerstag 17. August 2006, 14:21

Dienstag 4. September 2007, 17:06

ich habe micht werantwortet eine web page zu schreiben.....

unter anderen soll sie ein forum, benutzerwerwaltung usw beinhalten


zuerst hab ichs mit django probiert allerdings hab ich die ganze zeit fehlermeldungen gekriegt, die mir nichts sagten, auserdem sagten manche fehlermeldungen nichtmal in welchen file und zeile sie ge`raise`t wurden

dan hab ich was anderes versucht:
und zwar PHP maessig einfach und pragmatisch SQL befehle nicht versteckt, form validation fuer jede einzelne form selber geschrieben... usw
irgendwann hab ich nicht mehr durchgeblickt und weil ich viel arbeitete aber irgendwie nicht vorankam hab ich alles in die tonne geworfen

jetzt beim dritten anlauf ist meine taktik anders:
alles sauber, stabil, modular und selber zu schreiben
ich hab sogar ein eigenen orm gemacht.
es hat lange gedauert bis ich alles so weit hatte das ich es testen kann.
jetzt wo ich alles zusammen habe.....
geht es immer noch nicht meiner vorestellung entsprechend voran :cry:
SQLite beschwert sich andauernd wegen irgendwelchen murks, meine template engine (jinja) gibt nicht immer gerade praezise fehlermeldungen
und weil mirlangsam die lust vergeht, wird mein code immer unuebersichtlicher und "schmutziger" und beinhaltete immer mehr provisorische sachen, die auf einem "productive enviroment" garantiert nicht laufen werden



ist es den tatsaechlich so schwierig ne weppage zu schreiben?
irgendwelche tips?
cp != mv
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Dienstag 4. September 2007, 17:38

Costi hat geschrieben:ist es den tatsaechlich so schwierig ne weppage zu schreiben? irgendwelche tips?
Hallo Costi!

Ja, ich rate deshalb auch jedem Anfänger, zuerst mal die Finger von komplexen Websites zu lassen. Der Anfang sieht immer so schön einfach aus. Mal schnell ein paar HTML-Tags, ein paar Formulare... So einfach ist es doch wieder nicht. ;-)

Aber mit einem einfachen Framework kann man sich ein wenig entlasten. Ich erwarte mir von einem Framework nicht, dass es mir die Validierung von Formularen abnimmt. Viel mehr erwarte ich, dass es mir die Probleme in kleinen Portionen liefert, die ich dann ebenfalls in kleinen Portionen lösen und zurück liefern kann.

Wenn ich z.B. möchte, dass ein Kunde ein HTML-Formular mit einer Anfrage ausfüllen kann und diese Anfrage per Email an mich geschickt werden soll, dann ist das **ein** Problem und muss nicht unbedingt in eine rießige Applikation gestopft werden.

Ich habe mir vor Kurzem mal CherryPy angesehen und bin immer noch absolut davon begeistert, wie einfach die Dinge jetzt geworden sind.

Jede Seite ist eine Datei im Dateisystem. Genauer gesagt eine Cheetah-Vorlage. Diese Vorlagen verhalten sich ziemlich autonom. Das heißt, dass ich sie nicht explizit ins Hauptprogramm aufnehmen muss. (so wie bei PHP)

In die Cheetah-Vorlagen kann ich Python-Module importieren. Das heißt: Wenn ich z.B. ein Python-Modul habe, in dem es eine Funktion zum Versenden von Emails gibt, dann importiere ich es in die Cheetah-Vorlage und verwende sie von der Vorlage aus. Ich gehe nicht (oder nur selten) den Umweg über die Hauptanwendung.

Natürlich gibt es Dinge, die in der Hauptanwendung besser aufgehoben sind. Z.B. Datenbankverbindungen usw. (schon wegen dem Threading). Aber auch in diesem Fall importiere ich mir die gewünschte Funktion in die Cheetah-Vorlage und rufe diese von der Cheetah-Vorlage aus auf.

Diese Vorgehensweise hat meinen Entwicklungsprozess so einfach gemacht, wie ich ihn von Zope her kennengelernt hatte. Nur mit dem Vorteil, dass ich kein Zope mit mir rum schleppen muss und einfacher alles tun kann was ich will.

Hier mein Erfahungsbericht: http://www.python-forum.de/topic-10807.html

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Dienstag 4. September 2007, 18:35

Costi hat geschrieben:zuerst hab ichs mit django probiert allerdings hab ich die ganze zeit fehlermeldungen gekriegt, die mir nichts sagten, auserdem sagten manche fehlermeldungen nichtmal in welchen file und zeile sie ge`raise`t wurden
Komisch. Ich nutze Django quasi professionell und habe nur sehr shr wenige Fehlermeldungen bekommen die mir nichts sagen. Aber ich habe auf #django gefragt und meine Fragen dazu wurden eigentlich immer geklärt. Irgendwas machst du da wohl falsch.
Costi hat geschrieben:jetzt beim dritten anlauf ist meine taktik anders:
alles sauber, stabil, modular und selber zu schreiben
ich hab sogar ein eigenen orm gemacht.
Wenn das ORM-mäßige was du da gepostet hast, zu der Seite gehört dann verfehlt es die Kategorieren sauber, stabil und modular. Ab dem Punkt wo man sich ein ORM selbst schriebt hat man in aller Regel schlichtweg etwas falsch gemacht.
Costi hat geschrieben:es hat lange gedauert bis ich alles so weit hatte das ich es testen kann.
Klar. Daher schreibt auch niemand sein ORM selbst, niemand seine Templatesprache selbst. Manchmal werden Frameworks selbstgebaut, das ist aber auch schon alles.
Costi hat geschrieben:geht es immer noch nicht meiner vorestellung entsprechend voran :cry:
SQLite beschwert sich andauernd wegen irgendwelchen murks,
Dann ist dein ORM buggy.
Costi hat geschrieben:meine template engine (jinja) gibt nicht immer gerade praezise fehlermeldungen
Dann hättest du das vorher bedenken müssen, bevor du Jinja genommen hast.
Costi hat geschrieben:und weil mirlangsam die lust vergeht, wird mein code immer unuebersichtlicher und "schmutziger" und beinhaltete immer mehr provisorische sachen, die auf einem "productive enviroment" garantiert nicht laufen werden
Und wie sollen wir dir helfen, dass dir die Lust nicht vergeht?
Costi hat geschrieben:ist es den tatsaechlich so schwierig ne weppage zu schreiben?
irgendwelche tips?
Nein, so schwierig ist es nicht. Aber man muss sich eben mit Dokumentation auseinandersetzen, man muss sich mit den Libs auseinandersetzen die man verwenden will. Und man muss wissen wo die eigenen Grenzen liegen, und wo man lieber auf erprobte Lösungen ausweicht. Ich würde nicht einen Finger krumm machen, ein Framework zu schrieben. Dazu gibt es viel zu viele, viel zu gute Frameworks die ich nur anzupassen brauche.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

Dienstag 4. September 2007, 20:06

Leonidas hat geschrieben:
Costi hat geschrieben:jetzt beim dritten anlauf ist meine taktik anders:
alles sauber, stabil, modular und selber zu schreiben
ich hab sogar ein eigenen orm gemacht.
Wenn das ORM-mäßige was du da gepostet hast, zu der Seite gehört dann verfehlt es die Kategorieren sauber, stabil und modular. Ab dem Punkt wo man sich ein ORM selbst schriebt hat man in aller Regel schlichtweg etwas falsch gemacht.
Costi hat geschrieben:es hat lange gedauert bis ich alles so weit hatte das ich es testen kann.
Klar. Daher schreibt auch niemand sein ORM selbst, niemand seine Templatesprache selbst. Manchmal werden Frameworks selbstgebaut, das ist aber auch schon alles.
Costi hat geschrieben:meine template engine (jinja) gibt nicht immer gerade praezise fehlermeldungen
Dann hättest du das vorher bedenken müssen, bevor du Jinja genommen hast.
Costi hat geschrieben:ist es den tatsaechlich so schwierig ne weppage zu schreiben?
irgendwelche tips?
Nein, so schwierig ist es nicht. Aber man muss sich eben mit Dokumentation auseinandersetzen, man muss sich mit den Libs auseinandersetzen die man verwenden will. Und man muss wissen wo die eigenen Grenzen liegen, und wo man lieber auf erprobte Lösungen ausweicht. Ich würde nicht einen Finger krumm machen, ein Framework zu schrieben. Dazu gibt es viel zu viele, viel zu gute Frameworks die ich nur anzupassen brauche.
Erstmal zu Jinja: Seit der Version 1.0 (und folgende) wurde sehr stark die verwendung von verbessertem Debugging implementiert. Fehlermeldungen, die du nicht deuten kannst, müssen nicht unpräzise sein. Das liegt in der Natur... dir kommt es natürlich "groß, kompliziert" vor. Doch gerade Jinja hilft da viel.

Wo wir bei Frameworks sind. Die sind ja nicht umsonst entwickelt worden. Django, TurboGears, Pylons und viele andere, die sich wirklich zu einer breiten Front entwickelt haben und mit denen fast alles möglich ist.

EIn ORM haben auch alle mitgeliefert. Zum Glück... ich bekomme gerade einen Einblick, wie kompliziert solch ein ORM sein kann, bei meiner Mithilfe bei Storm. Ich persönlich würde mir so etwas weder zutrauen noch zumuten. Das währe glatte Zeitverschwendung, denn dafür gibt es andere wirklich exzelente, die es wirklich können. SQLAlchemy, Storm, SQLObject, Dejavu, (bald) Geniusql und (leider) viele andere...
Alle sind stark anpassbar und beeinflussen die eigentliche Applikation so wenig wie möglich, was sie wirklich gut können. (integrieren sich also prächtig)


Also wenn du nicht gerade ein wirklich komplett neues Konzept brauchst, wirklich etwas ganz explizites machst, etwas sehr kompliziertes... nimm etwas fertiges. Denn (wie schon oben erwähnt) selbst bei komplizierten Dingen, wo es um einige Anpassungen geht, sind heutige Frameworks auch nicht mehr so schlimm. CherryPy, kann man wunderbar anpassen, erweitern und konfigurieren. Gepaart mit einer ordentlichen Template Engine und einem ORM (HowTos gibts übrigens im CP Wiki) bekommst du ein unschlagbar dynamisches und starkes System. Wem das wieder zu viel ist, für den gibts Django & co.


MfG EnTeQuAk
Costi
User
Beiträge: 544
Registriert: Donnerstag 17. August 2006, 14:21

Dienstag 4. September 2007, 20:16

dass orm (http://paste.pocoo.org/show/3448/) ist das einzige was 100% klappt
obwohl er aus nur knapp ueber 100 lines besteht
ist er doch ganz hilfreich:

Code: Alles auswählen

from orm import *
import sqlite3

conn = sqlite3.connect(':memory:')

conn.cursor().execute("""
CREATE TABLE users
	(nickname char(20) primary key,
	pwd char(10),
	email char(50),
	firstname char(50),
	lastname char(50),
	rights char(50))
""")


class UsersResult(Result):
	def get_name(self):
		return self['firstname'] + ' ' + self['lastname'] 
class UsersTable(Table):
	def get_all_foos(self):
		return cursor2result_objects(self.exe('SELECT <pk_name> from <table> where firstname=?', "foo"), self.take)

users_table = UsersTable(table_name="users", pk_name='nickname', result_class=UsersResult, connection=conn)


my_user = users_table.create('peter')
my_user['firstname'] = 'foo'
print my_user
print
another_user = users_table.create({'email': 'bill@gates.com', 'firstname': 'foo', 'nickname': 'bill', 'lastname': 'gaga'})
print
print users_table.get_all_foos()
print
bill = users_table.search('bill')
print bill
print bill.exists()
print bill
print
print bill.get_name()
bill.delete()


#===========OUTPUT==========
#        INSERT INTO users (nickname) VALUES (?) | ('peter',)
#        UPDATE users SET firstname = ? WHERE nickname=? | ('foo', 'peter')
#<UsersResult nickname=peter (confirmed to exist)>
#
#        INSERT INTO users ("lastname", "nickname", "email", "firstname") VALUES (?, ?, ?, ?) | ('gaga', 'bill', 'bill@gates.com', 'foo')
#
#        SELECT nickname from users where firstname=? | ('foo',)
#[<UsersResult nickname=peter (confirmed to exist)>, <UsersResult nickname=bill (confirmed to exist)>]
#
#<UsersResult nickname=bill (not confirmed to exist)>
#        SELECT count(nickname) FROM users WHERE nickname=? | ('bill',)
#True
#<UsersResult nickname=bill (confirmed to exist)>
#
#        SELECT firstname FROM users WHERE nickname=? | ('bill',)
#       SELECT lastname FROM users WHERE nickname=? | ('bill',)
#foo gaga
#        DELETE FROM users WHERE nickname=? | ('bill',)
cherypy benutz ich ja schon...
aber alles komplett auf ein neues framework auflegen... hmmm
cp != mv
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

Dienstag 4. September 2007, 21:48

Also Jinja ist beim Error Reporing genauer als so manche andere Template Engine. Wenn mal doch wo ein Fehler auftaucht der nicht debuggbar ist würde mich das interessieren :-)
TUFKAB – the user formerly known as blackbird
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Mittwoch 5. September 2007, 21:25

Costi hat geschrieben:dass orm (http://paste.pocoo.org/show/3448/) ist das einzige was 100% klappt
Eben hieß es noch:
Costi hat geschrieben:SQLite beschwert sich andauernd wegen irgendwelchen murks
Also was jetzt?
My god, it's full of CARs! | Leonidasvoice vs Modvoice
apollo13
User
Beiträge: 827
Registriert: Samstag 5. Februar 2005, 17:53

Mittwoch 5. September 2007, 21:41

Ganz einfach: Das ORM kann nix dafür das Sqlite meckert ;)
Costi
User
Beiträge: 544
Registriert: Donnerstag 17. August 2006, 14:21

Mittwoch 5. September 2007, 21:43

wenn es klappt dan klappt es


das problem ist nur das ich sqlite3 nicht wie erwuenscht unter cherrypy zum laufen bringe, (weils gethreadet ist, und ``thread_data`` hilft mir auch nicht viel weiter)

und es manchmal irgendwie sowas agt wie "database is locked"

ausserdem haben INSERT statements nur manchmal eine wirkung

ich krieg es auch nur unter erhoerten zeitaufwand CREATE TABLE statements syntaktisch korrekt zu scheriben (gut, dafuer kann aber sqlite3 nichts)

EDIT:
Ganz einfach: Das ORM kann nix dafür das Sqlite meckert Wink
oder so :lol:
cp != mv
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Mittwoch 5. September 2007, 21:46

Costi hat geschrieben:das problem ist nur das ich sqlite3 nicht wie erwuenscht unter cherrypy zum laufen bringe, (weils gethreadet ist, und ``thread_data`` hilft mir auch nicht viel weiter)
CherryPy hat insbesondere in Version 2.x enorme Threading-Probleme gehabt, wurden scheinbar immer noch nicht gelöst. Aber hey, es gibt andere Libs, die mit Threads gut umgehen können.
Zuletzt geändert von Leonidas am Mittwoch 5. September 2007, 21:47, insgesamt 1-mal geändert.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
BlackJack

Mittwoch 5. September 2007, 21:46

Na das *muss* doch an SQLite liegen, oder etwa nicht!? :twisted:
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Mittwoch 5. September 2007, 22:15

Costi hat geschrieben:das problem ist nur das ich sqlite3 nicht wie erwuenscht unter cherrypy zum laufen bringe, (weils gethreadet ist, und ``thread_data`` hilft mir auch nicht viel weiter)
und es manchmal irgendwie sowas agt wie "database is locked"
Hallo Costi!

Die Sache ist ganz einfach.

CherryPy kann, in der Standardeinstellung, bis zu 10 Threads gleichzeitig aufmachen. Wenn du also in "thread_local" eine Verbindung zu einer SQLite-Datenbank aufmachst, dann können bis zu 10 Verbindungen zu SQLite gleichzeitig offen sein. Dafür wurde SQLite nicht gemacht. Wenn du von zwei oder mehreren Threads aus, gleichzeitig in eine Tabelle schreiben möchtest, dann hat einer der Threads den Vorrang und alle anderen Threads bekommen den Fehler, dass die Datenbank gesperrt ist. Da kann doch CherryPy nichts dafür. SQLite ist eine Desktop-Datenbank, die mit konkurrierenden Zugriffen nicht perfekt umgehen kann. Dafür wurde sie aber auch nicht geschrieben.

Lösung: Verwende PostgreSQL. Das wurde genau dafür gemacht. Das kann perfekt mit konkurrierenden Datenbankzugriffen umgehen.

Wenn du keine "gscheide" Website machen willst, also einfach etwas was bei dir lokal läuft und nicht gleichzeitig mehrere Benutzer bedienen soll, dann kannst du das Problem umgehen, indem du CherryPy so einstellst, dass es nur noch einen Thread verwendet.

Du könntest dir aber auch die Arbeit an tun und mit "Locks" arbeiten. Bei schreibenden Datenbankzugriffen vorher einen "Lock" erstellen und nach dem Schreiben wieder lösen. So ein Lock wirkt threadübergreifend. Du musst nur vor jedem schreibenden Datenbankzugriff prüfen ob so ein Lock schon gesetzt ist. Wenn ja, dann musst du warten, bis du einen Lock zugewiesen bekommst...

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Mittwoch 5. September 2007, 22:19

Leonidas hat geschrieben:CherryPy hat insbesondere in Version 2.x enorme Threading-Probleme gehabt, wurden scheinbar immer noch nicht gelöst.
Hallo Leonidas!

Ich habe noch nichts von irgendwelchen Threading-Problemen von CherryPy 3.x gehört. Immer nur, dass falsch damit umgegangen wurde.

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

Donnerstag 6. September 2007, 15:02

Hallo alle zusammen!


Ich muss Gerold zustimmen, CherryPy 3.x kann wunderbar mit Threads umgehen. Wie es bei den Vorgängerversionen war, kann ich nicht sagen.

Wenn du unbedingt ein Objekt in CherryPy`s ``thread_data`` brauchst, kannst du folgendes machen:

(Ein simples Beispiel mit Storm als ORM)

Code: Alles auswählen

database_uri = "sqlite:"
def set_connection(threadid):
    cherrypy.thread_data.store = Store(create_database(database_uri))
cherrypy.engine.subscribe('start_thread', set_connection)
So führt die CherryPy-Engine für jeden Thread, der von ihr gestartet werden muss diese Funktion (kann jegliches `callable` sein) aus.
Was allerdings das SQLite-Eigene Problem der `Lock`s nicht umgeht.
Man beachte, das dies afaik nur mit dem aktuellen Trunk (alpha) funktioniert. Wie die Engine das davor verwaltet hat, weiß ich nicht auf anhieb, ließe sich aber auf der Mailingliste oder im IRC erfragen, bei bedarf.

MfG EnTeQuAk
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Donnerstag 6. September 2007, 17:35

Hallo!

Das geht sogar noch einfacher:

Code: Alles auswählen

try:
    conn = cherrypy.thread_data.connection
except NameError:
    conn = cherrypy.thread_data.connection = sqlite3.connect("...")

cur = conn.cursor()
...
Wenn man sich dann noch einen globalen "Schreib-Lock" zulegt, dann ist das mit SQLite auch kein Problem mehr.

Irgendwo global einen Lock erstellen:

Code: Alles auswählen

import threading
global_dblock = threading.Lock()
Vor dem Schreiben in die Datenbank:

Code: Alles auswählen

global_dblock.acquire()
Und nach dem Schreiben den Lock wieder frei geben:

Code: Alles auswählen

global_dblock.release()
Schon sind die konkurrierenden Schreibzugriffe auf SQLite kein Problem mehr. So passieren die Schreibzugriffe nur mehr hintereinander. Lesezugriffe können gleichzeitig, also weiterhin ohne Lock arbeiten.

Wenn aber jetzt auch noch mehrere CherryPy-Instanzen gleichzeitig auf die SQLite-Datenbank "schreibend" zugreifen sollen, dann wird es Zeit, endlich auf PostgreSQL umzusteigen. ;-)

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Antworten