CGI/modPython/fastCGI print-Buffer -> Threadsave?!?!

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Also bisher ist es so, das Plugins in PyLucid einfach print ausgaben machen durften. Diese werden per stdout-Buffer abgefangen und in die CMS-Seite eingebaut...

Nun hab ich gehört das das generell nicht Thread-Safe ist. Ich hab allerdings bisher keine Ahnung von Threads und Co.

Die einfachste, aber aufwendigste, Möglichkeit ist natürlich alle print-Ausgaben um zu ändern und request.write() zu nutzten... Einfach wäre es allerdings stdout.write() nach request.write() umzubieten... Wäre das Threadsafe?

Was ist generell bei Umsetzung "CGI only" nach WSGI zu beachten???

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
BlackJack

Auch direkt `write()` auf Dateiobjekten von mehreren Threads ist wahrscheinlich nicht thread-safe. Aber brauchst Du das denn unbedingt? Hast Du denn mehrere Threads laufen, die auf das selbe Objekt nebenläufig schreiben?
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Es ist die Frage was mit thread-safe gemeint ist. Mehrere Zugriffe auf das selbe Objekt sind von Python aus natürlich thread-safe, weil es das GIL gibt. Wenn es aber darum geht dass eine gewisse Semantik eingehalten wird bei den darunterliegenden Objekten (zum Beispiel die Schreibreihenfolge bei .write() aus mehreren Threads), dann hängt das vom Betriebssystem ab.

print in einem CGI ist nichts anderes, wobei Du Dich da halt echt auf CGI beschränkst, weil das print das globale sys.stdout nimmt, was eben nicht per Thread anders ist. Es hilft Dir auch nichts wenn Du sys.stdout umbiegst, das führt nur dazu dass dann alle Threads die gleichzeitig eine Seite probieren zu schreiben in die Ausgabe eines dieser Threads läuft. Deswegen gibts das request-Objekt mit request.write(), das request-Objekt ist unik in jedem Thread, und dementsprechend kann über das Objekt auch unterschieden werden wohin die Ausgabe gehen soll.

Es führt also kein Weg vorbei wenn Du WSGI (bzw. gethreadete Server) unterstützen willst alle Aufrufe von print durch request.write zu ersetzen, und vor allen Dingen zuzuschauen dass das request Objekt bis dahin wo Du es einsetzt durchgereicht wird. Es reicht nicht eine globale Variable zu setzen, das bringt aus dem selben Grund nichts wie sys.stdout neu zu setzen, da alle Threads sich den Zustand globaler Variablen teilen, aber request Thread-spezifisch ist.
--- Heiko.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Also generell geht es mir um threading Server. Ich dachte bei modPython/fastCGI ist das immer der Fall. Ist das nicht so?
Leider hab ich in der Richtung keine Erfahrung.

Schade ich dachte eigentlich ich könnte quasi pro Thread stdout verbiegen. Das das dann global geschiet und deswegen nicht geht, leuchtet mir ein.

Ist es dann damit getan, das ich alle print's durch request.write() ersetzte?

Was ist allgemein noch zu beachten? Ich muß wahrscheinlich für SQL-Connection-Pool gedanken machen, was? Da gibt es allerdings schon was: http://wsgiarea.pocoo.org/trac/browser/ ... atabase.py

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

Also du _kannst_ es weiterleiten. Du müsstest nur eine klasse schreiben, die vorer mal schaut aus welchem Thread das ganze kommt, über ein globales Dict jedem thread ein request objekt dem thread zuordnen und dann an den schreiben.

Aber was spricht gegen ein request.write?
TUFKAB – the user formerly known as blackbird
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Hört sich kompliziert an, dene Lösung :) Dann änder ich halt alles zu request.write()...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Antworten