SQLAlchemy + Threads

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.
Jan.O
User
Beiträge: 61
Registriert: Samstag 26. April 2008, 00:32

Montag 20. April 2009, 17:21

Hi,

Ich suche hier Rat zu einem "hack" von leuten die Erfahrung mit SQLAlchemy in Anwendungen mit Threads haben.

Und zwar geht es mir um die Frage, wie man die Sessions pro thread erstellt. Soweit ich das verstanden habe, wird für jeden Thread eine Session mit der methode scoped_session(...) erzeugt und dann in einem object des typs threading.local abgelegt, richtig?
also zB so:

Code: Alles auswählen

from sqlalchemy.orm import scoped_session, sessionmaker
from threading import local

# framework.thread_data = local()

def beim_starten_eines_threads():
    framework.thread_data.session = scoped_session(sessionmaker(...))
Aber ich ich will nicht jedes mal framework.thread_data.session benutzen müssen, um auf die db zuzugreifen. scoped_session macht nichts weiter als ein objekt der Klasse ScopedSession zu erzeugen. Ist der folgende "hack" nicht viel genialer?

Code: Alles auswählen

from threading import local
from sqlalchemy.orm.scoping import ScopedSession

class LocalSession(local, ScopedSession):
    def __init__(self, session_factory, scopefunc=None):
        ScopedSession.__init__(self,session_factory, scopefunc=scopefunc)

def beim_starten_eines_threads():
    db =  LocalSession(sessionmaker(...))
Hat doch den selben effekt, nur dass das object jetzt nur noch db heißt. Habe ich da einen haken übersehen? Ist die varibale jetzt vielleicht nicht mehr überall im webframework "erreichbar", wo sie vorher erreichbar war?

Jan
lunar

Montag 20. April 2009, 19:33

Ich denke, du hast nicht verstanden, wie scoped_session funktioniert. Man erzeugt nicht pro Thread eine scoped_session, sondern man erzeugt die scoped_session genau einmal global. Diese globale Session weiß dann automatisch, in welchen Thread sie sich befindet.
Jan.O
User
Beiträge: 61
Registriert: Samstag 26. April 2008, 00:32

Montag 20. April 2009, 20:00

lunar hat geschrieben:Ich denke, du hast nicht verstanden, wie scoped_session funktioniert. Man erzeugt nicht pro Thread eine scoped_session, sondern man erzeugt die scoped_session genau einmal global. Diese globale Session weiß dann automatisch, in welchen Thread sie sich befindet.
Hmm... Bei web.py wird das objekt auf web.ctx abgelegt. Habe ich die ctx variable nicht verstanden, oder hat web.py scoped_session nicht verstanden?
lunar

Montag 20. April 2009, 20:06

Mit web.py kenne ich mich nicht aus ...

Btw, bist du sicher, dass du das verwenden möchtest? Man sagt davon, es wäre mies geschrieben und eigentlich ziemlich kaputt ... zu den verbreiteten Frameworks gehört es auch nicht wirklich.
Jan.O
User
Beiträge: 61
Registriert: Samstag 26. April 2008, 00:32

Montag 20. April 2009, 20:18

lunar hat geschrieben:Mit web.py kenne ich mich nicht aus ...

Btw, bist du sicher, dass du das verwenden möchtest? Man sagt davon, es wäre mies geschrieben und eigentlich ziemlich kaputt ... zu den verbreiteten Frameworks gehört es auch nicht wirklich.
Ähnliches hat mir gerade auch Leonidas mitgeteilt. Ich suche ein Framwork...
... in welchem ich SQLAlchemy, Jinja2 und memcache benutzen kann
... welches nicht davon ausgeht, dass ich bestimmte Features benutze, welche ich nicht benutzen will (Bsp. Jango ORM)
... welches die überflüssige arbeit möglichst reduziert
.. welches gutes URL mapping besitzt, sodass ich mein Projekt in Pakete unterteilen kann
... welches stabil und akzeptabel performant ist

Gibts da neben Web.py noch ein framework, welches diese anforderung erfüllt?
DasIch
User
Beiträge: 2465
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Montag 20. April 2009, 20:23

Das klingt nicht wirklich als ob du ein Framework suchst. Schon mal einen Blick auf Werkzeug geworfen?
Jan.O
User
Beiträge: 61
Registriert: Samstag 26. April 2008, 00:32

Montag 20. April 2009, 20:30

DasIch hat geschrieben:Das klingt nicht wirklich als ob du ein Framework suchst. Schon mal einen Blick auf Werkzeug geworfen?
Ja, aber nicht sehr tiefgehend, da ich schon ziemlich bald das gefühl hatte, dass man bei Werkzeug zu viel selbst machen muss.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Montag 20. April 2009, 20:45

Jan.O hat geschrieben:Ich suche ein Framwork...
... in welchem ich SQLAlchemy, Jinja2 und memcache benutzen kann
... welches nicht davon ausgeht, dass ich bestimmte Features benutze, welche ich nicht benutzen will (Bsp. Jango ORM)
... welches die überflüssige arbeit möglichst reduziert
.. welches gutes URL mapping besitzt, sodass ich mein Projekt in Pakete unterteilen kann
... welches stabil und akzeptabel performant ist
Hallo Jan.O!

Das sind fast genau die Gründe, weshalb ich CherryPy für mich ausgesucht habe. Und ich wurde nicht enttäuscht. CherryPy ist wirklich genial einfach -- hält aber trotzdem die unangenehme Arbeit von mir ab.

- http://cherrypy.org/
- http://halvar.at/python/cherrypy_cheetah/

Probiere es einfach mal aus. Du brauchst für dieses Beispiel CherryPy und Cheetah.
CherryPy: http://cherrypy.org
Cheetah für Python 2.5: http://www.cheetahtemplate.org/
Cheetah für Python 2.6: http://rtyler.github.com/cheetah/

Code: Alles auswählen

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

import cherrypy
from Cheetah.Template import Template

# Das hier steht normalerweise in eigenen Vorlagendateien
INDEX_TEMPLATE = """<html>
<head></head>
<body>
  <form action="showformdata">
    <p>Vorname: <input type="text" name="vorname" /></p>
    <p>Nachname: <input type="text" name="nachname" /></p>
    <p><input type="submit" value="anzeigen" /></p>
  </form>
</body>
</html>
"""

# Das hier steht normalerweise in eigenen Vorlagendateien
SHOWFORMDATA_TEMPLATE = """<html>
<head></head>
<body>
  <p>Vorname: $vorname</p>
  <p>Nachname: $nachname</p>
</body>
</html>
"""


class Root(object):
    
    def index(self, *args, **kwargs):
        template = Template(INDEX_TEMPLATE)
        return str(template)
    index.exposed = True
    
    
    def showformdata(self, vorname = "", nachname = ""):
        template = Template(SHOWFORMDATA_TEMPLATE)
        template.vorname = vorname
        template.nachname = nachname
        return str(template)
    showformdata.exposed = True


def main():
    cherrypy.quickstart(Root())


if __name__ == "__main__":
    main()
mfg
Gerold
:-)
Zuletzt geändert von gerold am Montag 20. April 2009, 21:34, insgesamt 2-mal geändert.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
nemomuk
User
Beiträge: 862
Registriert: Dienstag 6. November 2007, 21:49

Montag 20. April 2009, 21:05

Naja, was muss man bei Werkzeug selbst machen? Man muss sich einmal ein funktionierendes System/einen Aufbau zusammenbauen, das in seiner App umsetzen und dann kann man damit loslegen. Der Vorteil davon ist: du bist sehr frei und kannst genau das machen, was und wie du willst. Ich verwende Werkzeug mit Jinja und SQLAlchemy (letzteres erst seit kurzem) und komme perfekt damit klar. Performancetechnisch habe ich noch keine Vergleiche gemacht - jemand anders vllt. mehr Infos dazu?
Jan.O
User
Beiträge: 61
Registriert: Samstag 26. April 2008, 00:32

Montag 20. April 2009, 23:11

gerold hat geschrieben:CherryPy ist wirklich genial einfach -- hält aber trotzdem die unangenehme Arbeit von mir ab.
Es gibt nur einen Grund warum ich CHerrpy in diesem fall nicht einsetzen möchte: weil man an die objektorientierte URL-Bildung gebunden ist.
Folgender fiktiver Navigationsablauf wäre mich Cherrypy nicht möglich

http://www.example.com/users/
http://www.example.com/users/Peter/
http://www.example.com/users/Peter/images/
http://www.example.com/users/Peter/images/124/
http://www.example.com/users/Peter/images/124/comment/

Ich glaube man kann irgendwie einen eigenen URL-Mapper in cherrypy reinprogrammieren. Noch ein Link. Damit werde ich mich aber erst morgen beschäftigen. Gute Nacht @all.

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

Dienstag 21. April 2009, 00:14

Jan.O hat geschrieben:Ich glaube man kann irgendwie einen eigenen URL-Mapper in cherrypy reinprogrammieren.
Hallo Jan.O!

Nicht "reinprogrammieren", sondern schlicht "nutzen". :-)
Ideal für dich dürfte der "RoutesDispatcher" sein. Dafür musst du aber noch das "routes"-Paket mit "easy_install" installieren.

Hier ist ein Beispiel:

Code: Alles auswählen

#!/usr/bin/env python
#coding: utf-8
"""
Requirements
    - Python: http://python.org/
    - cherrypy: http://cherrypy.org/
    - routes: http://pypi.python.org/pypi/Routes/
"""

import cherrypy


class Root(object):
    
    def index(self, *args, **kwargs):
        retstr = (
            "Root-index<br>" +
            repr(args) + "<br>" +
            repr(kwargs)
        )
        return retstr
    index.exposed = True
    

class Users(object):
    
    def index(self, *args, **kwargs):
        retstr = (
            "Users-index<br>" +
            repr(args) + "<br>" +
            repr(kwargs)
        )
        return retstr
    index.exposed = True
    
    
    def get_user(self, *args, **kwargs):
        retstr = (
            "Users-get_user<br>" +
            repr(args) + "<br>" +
            repr(kwargs)
        )
        return retstr
    get_user.exposed = True
    
 
    def get_image(self, user, imageid):
        retstr = (
            "Users-get_image<br>" +
            "user: %s<br>" % user +
            "imageid: %s" % imageid
        )
        return retstr
    get_image.exposed = True

    
    def get_image_comment(self, user, imageid):
        retstr = (
            "Users-get_image_comment<br>" +
            "user: %s<br>" % user +
            "imageid: %s" % imageid
        )
        return retstr
    get_image_comment.exposed = True
    

def main():
    root = Root()
    root.users = Users()
    
    dispatcher = cherrypy.dispatch.RoutesDispatcher()
    dispatcher.connect(
        "users-index", "/users/", 
        controller = root.users, action = "index"
    )
    dispatcher.connect(
        "users-user", "/users/:user/", 
        controller = root.users, action = "get_user"
    )
    dispatcher.connect(
        "users-image", "/users/:user/images/:imageid", 
        controller = root.users, action = "get_image"
    )
    dispatcher.connect(
        "users-image-comment", "/users/:user/images/:imageid/comment", 
        controller = root.users, action = "get_image_comment"
    )

    app = cherrypy.tree.mount(root)
    conf = {"/users": {"request.dispatch" : dispatcher}}
    app.config.update(conf)
    cherrypy.quickstart(app)


if __name__ == "__main__":
    main()
Damit kannst du die oben genannten URLs verwenden.

mfg
Gerold
:-)

http://paste.pocoo.org/show/113472/
Zuletzt geändert von gerold am Mittwoch 22. April 2009, 13:43, insgesamt 1-mal geändert.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Jan.O
User
Beiträge: 61
Registriert: Samstag 26. April 2008, 00:32

Mittwoch 22. April 2009, 13:29

Sehr schön! Vielen Dank. Das ist so ziemlich genau das wonach ich gesucht habe. Ich werde CherryPy für das projekt verwenden
Benutzeravatar
Hyperion
Moderator
Beiträge: 7472
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Mittwoch 22. April 2009, 14:28

Wobei das mit Werkzeug auch schön einfach zu lösen ist - und da braucht man kein extra Routes-Modul. Wo liegt da also nun der große Unterschied frag ich mich gerade? (Denn Werkzeug war dem OP ja irgend wie zu "wenig" Framework)
lunar

Mittwoch 22. April 2009, 14:37

Werkzeug nimmt dem Programmierer wenig bis gar nichts ab, während CherryPy zumindest Sessionverwaltung, Routing und iirc auch Authentifizierung weitgehend automatisch kann.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7472
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Mittwoch 22. April 2009, 14:48

lunar hat geschrieben:Werkzeug nimmt dem Programmierer wenig bis gar nichts ab, während CherryPy zumindest Sessionverwaltung, Routing und iirc auch Authentifizierung weitgehend automatisch kann.
Ja ok, ich bezog mich grad auf das Routing, welches Werkzeug ebenso bietet (oder sehe ich das falsch?) - aber das andere sind da sicherlich Argumente für CherryPy. Da müßte man bei werkzeug ja wirklich noch Hand anlegen.

*seufz* Müßte dringend mal an meinen werkeug-Test-Applikationen weiter arbeiten ... wenn man doch mehr Zeit hätte ;-)
Antworten