Werkzeug: fragen zum Tutorial

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
zero-one
User
Beiträge: 58
Registriert: Dienstag 20. Mai 2008, 20:52

Hi,

da ich weiss das hier viele Werkzeug benutzen und auch der Entwickler sich hier rumtreibt stelle ich mal meine Frage diesbezueglich hier. Ich hoffe mal das ich nicht gesteinigt werde ;-)

Also zunaechst mal muss ich sagen das ich schon nen weilchen mich mit Werkzeug beschaeftige aber viele Sachen aus dem tutorial als gegeben gesehen habe... nun moechte ich mal hinterfragen warum das eigentlich so ist.

Vom hintergrund her muss ich noch sagen das ich wie sicher viele andere hier von PHP komme und deswegen da wohl so meine Probleme habe, evl. helfen die Antworten hier ja auch einigen leute die die gleichen Fragen haben .. so dann leg ma mal los :)

Code: Alles auswählen

session = scoped_session(lambda: create_session(application.database_engine,
                         transactional=True), local_manager.get_ident)

ok ich weiss, dass das hier nicht wirklich Werkzeug betrifft aber dennoch..
kann mir bitte jemand erklaeren was es mit der scoped_session und mit dem local_manager.get_ident im aufruf auf sich hat?

Ich bin in Sachen sqlalchemy eher sowas hier gewohnt

Code: Alles auswählen

engine = create_engine(connect_string)
Session = sessionmaker(bind=engine)
session = Session()
ausserdem ist mir die Bedeutung von local und LocalManager etwas schleierhaft.. ich hab in der Doku gelesen das man das irgendwie wegen Threads braucht oder so... koennte mir das evl. jemand nochmal etwas genauer erklaeren?

und noch was.. bezueglich local ... wieso muss man local.application = self machen?

Hoffe jemand kann etwas Licht bei mir ins Dunkel bringen :)

danke und beste Gruesse Zero-One
apollo13
User
Beiträge: 827
Registriert: Samstag 5. Februar 2005, 17:53

Nein, scoped_session haben ansich nichts mit werkzeug in dem Sinn zu tun, sondern eher mit WebApps im Allgemeinen, eine Erklärung gibt es hier: http://www.sqlalchemy.org/docs/04/sessi ... contextual
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

In meinem Model benutze ich diese Zeile (mit SA 0.5x):

Code: Alles auswählen

dbsession = scoped_session(sessionmaker())
Und in meiner Applikation:

Code: Alles auswählen

from myapp import models


class Application(object):

    def __init__(self, config):
        # [...]

        # Setup database connection.
        engine = engine_from_config(config, prefix='database_',
            convert_unicode=True)
        models.dbsession.configure(bind=engine)

    def __call__(self, environ, start_response):
        # [...]

        return ClosingIterator(
            response(environ, start_response),
            [models.dbsession.remove, local_manager.cleanup])

Die ganze Geschichte sorgt u. a. dafür, dass der Datenbank-Zugriff threadsicher erfolgt.
lunar

local und localmanager verwalten Objekte, die spezifisch für einen einzigen Ablauf sind (z.B. der Request). WSGI ist prinizpiell unabhängig von Server, es ist also nicht bekannt, in welcher Umgebung die Anwendung ausgeführt wird. Demnach ist auch unbekannt, welche Strategie der Server verwendet, um mehrere Requests parallel abzuarbeiten. So kann er forken (und geforkte Prozesse evtl. wiederverwenden) oder mehrere Threads starten.

Da es also gut möglich ist, dass innerhalb eines Prozesses dieser Anwendung Nebenläufigkeiten auftreten, müssen alle Funktionen reentrant sein. Das bedeutet, sie dürfen keinerlei globale Variablen referenzieren oder Singletons nutzen. local bietet nun die Möglichkeit, globale Objekte so zu verwalten, dass sie sicher von Nebenläufigkeiten sind. Dazu verwaltet local Objekte in einem speziellen Context, so dass ein Thread oder Greenlet nur auf Objekte zugreifen kann, die innerhalb desselben Context erzeugt wurden.

localmanager dient dazu, die context-gebundenen Objekte nach einem Request zu entfernen, damit keine alten Daten übrigbleiben, wenn ein Thread oder Prozess wiederverwendet wird.

Das SQLAlchemy-Konstrukt ist nötig, da SQLAlchemy Sessions nicht threadsicher sind. Über eine scoped session erzeugt SQLAlchemy je eine Session pro Kontext, so dass man eine einzige "session"-Variable hat, die man sicher ansprechen kann, aber trotzdem nicht Gefahr läuft, durch Nebenläufigkeiten inkonsistente Zustände zu erzeugen.

Bei PHP hattest du damit wahrscheinlich nie zu tun, weil man in PHP grundsätzlich eh nie threadsicher programmiert. PHP-Anwendungen werden eigentlich immer von Servern ausgeführt, die mehrere Prozesse starten.
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Ein `threadlocal` ist ein Proxy-Objekt, das (im Kontext von Web-Anwendungen) immer das zu dem aktuellen Request gehörende Objekt liefert. Hat mich bei Paste eine Weile gekostet, um das zu verstehen.

lunar hat geschrieben:Bei PHP hattest du damit wahrscheinlich nie zu tun, weil man in PHP grundsätzlich eh nie threadsicher programmiert. PHP-Anwendungen werden eigentlich immer von Servern ausgeführt, die mehrere Prozesse starten.
Deswegen wird auch PHP unter Debian entfernt, wenn man Apache als Worker installiert.
zero-one
User
Beiträge: 58
Registriert: Dienstag 20. Mai 2008, 20:52

Wow, danke fuer die ausfuehrlichen Antworten, ich denke ich habs jetzt so in etwa verstenden :)

Aber noch eine kleine Frage brennt mir unter den Naegeln :)

was hat es mit dem ominoesen local_manager.get_ident im scoped_session Aufruf auf sich?

Waere toll wenn jemand noch diese letzte Unklarheit beseitigen koennte.

Danke :)
lunar

local_manager.get_ident identifiziert den aktuellen Kontext eindeutig. Eine mögliche Art der Identifizierung könnte beispielsweise eine Kombination aus PID und Thread-ID sein. Natürlich ist das noch ein bisschen komplizierter, da Werkzeug afaik auch Greenlets unterstützt.

local_manager.get_ident wird im Übrigen nicht aufgerufen, dass wäre unsinnig und broken. Das erzeugte scoped_session Objekt erhält lediglich eine Referenz auf diese Methode.

Wenn nun auf die scoped session zugegriffen wird, wird diese Methode aufgerufen, um die ID des aktuellen Kontext zu ermitteln. Existiert bereits eine zu dieser ID passende Session, wird diese benutzt, andernfalls eine neue erzeugt.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Y0Gi hat geschrieben:
lunar hat geschrieben:Bei PHP hattest du damit wahrscheinlich nie zu tun, weil man in PHP grundsätzlich eh nie threadsicher programmiert. PHP-Anwendungen werden eigentlich immer von Servern ausgeführt, die mehrere Prozesse starten.
Deswegen wird auch PHP unter Debian entfernt, wenn man Apache als Worker installiert.
mod_php geht nicht mit Worker, aber es ist durchaus möglich FastCGI zu nutzen (mod_fcgid oder mod_fastcgi) und darüber das PHP-Binary auszuführen, welches unter Debian so kompiliert ist, dass FastCGI unterstütz wird. Nur machen das eben entsprechend wenige und nutzen MPM Prefork, weil man damit PHP trivial einrichten kann.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten