Seite 1 von 1

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

Verfasst: Donnerstag 9. Februar 2006, 21:38
von jens
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???

Verfasst: Donnerstag 9. Februar 2006, 23:16
von 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?

Verfasst: Donnerstag 9. Februar 2006, 23:27
von modelnine
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.

Verfasst: Freitag 10. Februar 2006, 07:32
von jens
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

Verfasst: Freitag 10. Februar 2006, 10:47
von mitsuhiko
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?

Verfasst: Freitag 10. Februar 2006, 15:35
von jens
Hört sich kompliziert an, dene Lösung :) Dann änder ich halt alles zu request.write()...