ubuntuusers.de

[Python / Bottle] Session-Struktur selber machen

Status: Gelöst | Ubuntu-Version: Ubuntu 10.10 (Maverick Meerkat)
Antworten |

Glocke

(Themenstarter)
Avatar von Glocke

Anmeldungsdatum:
1. März 2009

Beiträge: 880

Wohnort: Thüringen

Lysander schrieb:

Hui... du hast mal das OpenBook von Galileo gelesen, richtig?

Vergiss den mal schön, anders als in C++ sollte man den Destruktor in Python meiden.

kp woher ich den hab - glaube google. aber das openbook wars nicht 😛

warum sollte man den deiner meinung nach in python meiden und was sollte man stattdessen verwenden?

wegen race condition kam mir noch ne idee (die prüfung ob die id überhaupt gültig ist war jetzt mal schon früher und ist positiv ausgefallen - andernfalls wären wir in einem anderen zweig des konstruktors:

1
2
3
4
5
6
try:
        verschiebe sid.dat zu sid.lck
except datei nicht vorhanden:
        warten wie oben beschrieben
else:
        daten lesen aus sid.lck

(datei nicht vorhanden bedeutet - da nach voraussetzung entweder dat oder lck existieren - dass die session gesperrt ist und die lck vorhanden ist

sollte gehen, sofern das verschieben aka umbenennen atomar ist (was ich nicht genau weiß)....

Lysander

Avatar von Lysander

Anmeldungsdatum:
30. Juli 2008

Beiträge: 2669

Wohnort: Hamburg

Glocke schrieb:

kp woher ich den hab - glaube google. aber das openbook wars nicht 😛

warum sollte man den deiner meinung nach in python meiden und was sollte man stattdessen verwenden?

Lies es bei BlackJacks Kritik am OpenBook nach: http://bj.spline.de/python_openbook.html#destruktor

wegen race condition kam mir noch ne idee (die prüfung ob die id überhaupt gültig ist war jetzt mal schon früher und ist positiv ausgefallen - andernfalls wären wir in einem anderen zweig des konstruktors:

1
2
3
4
5
6
try:
        verschiebe sid.dat zu sid.lck
except: datei nicht vorhanden
        warten wie oben beschrieben
else:
        daten lesen aus sid.lck

sollte gehen, sofern das verschieben aka umbenennen atomar ist (was ich nicht genau weiß)....

Genau das hängt ja vom OS ab - auch das findet man durch das Studium der werkzeug-Lösung heraus.

Wenn man per mkstemp() eine temporäre Datei erzeugt und diese dann umbennen will, tritt ja gerade dieses Problem auf. (und mkstemp an sich ist ja laut Doku garantiert atomar)

Glocke

(Themenstarter)
Avatar von Glocke

Anmeldungsdatum:
1. März 2009

Beiträge: 880

Wohnort: Thüringen

bzgl. destruktor werde ich das speichern in eine save() methode verlegen und den destruktor aus dem quellcode entfernen. danke für den link!!

wegen os.rename() werde ich mich belesen.

DasIch

Avatar von DasIch

Anmeldungsdatum:
2. November 2005

Beiträge: 1130

Glocke schrieb:

Zunächst prüfe ich mittels os.path.isfile(filename) ob die lock-file existiert. [...]wenn die lock-file dann mal weg ist wird sofort eine neue lock-file erstellt[...]

Wenn os.path.isfile(filename) False zurückgibt und du danach erst eine Datei erstellst, kann es sein das zwischen dem Check und dem erstellen der Datei, ein anderer Prozess die Datei erstellt.

Schau dir an wie Werkzeug das macht. Die Implementation funktioniert und alles was sie tut und wie sie es tut hat sehr gute Gründe.

Glocke

(Themenstarter)
Avatar von Glocke

Anmeldungsdatum:
1. März 2009

Beiträge: 880

Wohnort: Thüringen

Lysander und ich waren beim Umbenennen der .dat auf .lck stehengeblieben. Wenn dies atomar geschieht, wird die Session race condition sicher gelockt (für mein Skript).

os.rename()

If successful, the renaming will be an atomic operation (this is a POSIX requirement).

Denke damit dürfte sich das Problem erledigt haben, oder?

Lysander

Avatar von Lysander

Anmeldungsdatum:
30. Juli 2008

Beiträge: 2669

Wohnort: Hamburg

Glocke schrieb:

os.rename()

If successful, the renaming will be an atomic operation (this is a POSIX requirement).

Denke damit dürfte sich das Problem erledigt haben, oder?

Auf POSIX kompatiblen Systemen ja. Auch das findet sich in werkzeug. Ich habe in meinem Beitrag bereits darauf Bezug genommen. Du musst halt im werkzeug Code nachgucken, wie das rename() dort durch Monkey-Patching bei NT like Systemen repariert wird.

Glocke

(Themenstarter)
Avatar von Glocke

Anmeldungsdatum:
1. März 2009

Beiträge: 880

Wohnort: Thüringen

Das skript wird eh nur auf POSIX-kompatiblen Linux-Servern zum Einsatz kommen. Unter dieser Restriktion sollten also keine weiteren Probleme auftreten, oder?

Lysander

Avatar von Lysander

Anmeldungsdatum:
30. Juli 2008

Beiträge: 2669

Wohnort: Hamburg

Glocke schrieb:

Das skript wird eh nur auf POSIX-kompatiblen Linux-Servern zum Einsatz kommen. Unter dieser Restriktion sollten also keine weiteren Probleme auftreten, oder?

Kommt dann eben noch drauf an, wie Du die Dateien erzeugst. Ansonsten: ja.

Glocke

(Themenstarter)
Avatar von Glocke

Anmeldungsdatum:
1. März 2009

Beiträge: 880

Wohnort: Thüringen

naja eine neue session erstellt die file mittels open. wobei ich ahne dass das wiederum zu race conditions führen kann ....

Lysander

Avatar von Lysander

Anmeldungsdatum:
30. Juli 2008

Beiträge: 2669

Wohnort: Hamburg

Glocke schrieb:

naja eine neue session erstellt die file mittels open, write("") und close. wobei ich ahne dass das wiederum zu race conditions führen kann ....

was man ja durch das Nutzen von mkstemp() umgehen kann... 😉

Genau diese Erkenntnis kann man aus dem Code von werkzeug gewinnen 😎

Glocke

(Themenstarter)
Avatar von Glocke

Anmeldungsdatum:
1. März 2009

Beiträge: 880

Wohnort: Thüringen

Lysander schrieb:

Genau diese Erkenntnis kann man aus dem Code von werkzeug gewinnen 😎

oder durch das lesen der python doc (was ich eben gemacht habe). ich schaffe es aber nicht die file mit korrektem namen zu erstellen - ich habe ständig irgendwelche anderen buchstaben dahinter.

1
2
3
>>> import tempfile
>>> tempfile.mkstemp(prefix="Beispiel", suffix=".dat", dir="/home/glocke/Desktop")
(3, '/home/glocke/Desktop/Beispiel4An6RG.dat')

Lysander

Avatar von Lysander

Anmeldungsdatum:
30. Juli 2008

Beiträge: 2669

Wohnort: Hamburg

Glocke schrieb:

Lysander schrieb:

Genau diese Erkenntnis kann man aus dem Code von werkzeug gewinnen 😎

oder durch das lesen der python doc (was ich eben gemacht habe).

Ok, ich Kombination eben - oder wie bist Du sonst auf mkstemp() gekommen?

ich schaffe es aber nicht die file mit korrektem namen zu erstellen - ich habe ständig irgendwelche anderen buchstaben dahinter.

1
2
3
>>> import tempfile
>>> tempfile.mkstemp(prefix="Beispiel", suffix=".dat", dir="/home/glocke/Desktop")
(3, '/home/glocke/Desktop/Beispiel4An6RG.dat')

Was meinst Du mit "dahinter"? Sieht doch gut aus!

Glocke

(Themenstarter)
Avatar von Glocke

Anmeldungsdatum:
1. März 2009

Beiträge: 880

Wohnort: Thüringen

Lysander schrieb:

Glocke schrieb:

oder durch das lesen der python doc (was ich eben gemacht habe).

Ok, ich Kombination eben - oder wie bist Du sonst auf mkstemp() gekommen?

python doc - gegoogelt nach "python create file atomic" etc.

1
2
3
>>> import tempfile
>>> tempfile.mkstemp(prefix="Beispiel", suffix=".dat", dir="/home/glocke/Desktop")
(3, '/home/glocke/Desktop/Beispiel4An6RG.dat')

Was meinst Du mit "dahinter"? Sieht doch gut aus!

fast: die file sollte /home/glocke/Desktop/Beispiel.dat heißen. ich will dann mit der sid als prefix erzeugen. und da beim prüfen ob die sid vergeben ist geguckt wird ob eine datei namens <sid>.dat oder <sid>.lck existiert, stört das teil hinter dem prefix.

Lysander

Avatar von Lysander

Anmeldungsdatum:
30. Juli 2008

Beiträge: 2669

Wohnort: Hamburg

Glocke schrieb:

Lysander schrieb:

Glocke schrieb:

oder durch das lesen der python doc (was ich eben gemacht habe).

Ok, ich Kombination eben - oder wie bist Du sonst auf mkstemp() gekommen?

python doc - gegoogelt nach "python create file atomic" etc.

Naja, es wurde in diesem Thread ja auch schon zig mal erwähnt...

1
2
3
>>> import tempfile
>>> tempfile.mkstemp(prefix="Beispiel", suffix=".dat", dir="/home/glocke/Desktop")
(3, '/home/glocke/Desktop/Beispiel4An6RG.dat')

Was meinst Du mit "dahinter"? Sieht doch gut aus!

fast: die file sollte /home/glocke/Desktop/Beispiel.dat heißen. ich will dann mit der sid als prefix erzeugen. und da beim prüfen ob die sid vergeben ist geguckt wird ob eine datei namens <sid>.dat oder <sid>.lck existiert, stört das teil hinter dem prefix.

Na das ist eben ja der Clou eines Temp-Files - es soll ja einzigartig sein. Daher musst Du es ja nach dem Anlegen entsprechend umbenennen mit os.rename(). Auch das hatten wir ja nun schon. Letztlich ist das eben genau die Idee hinter dem Code in Werkzeug!

Ich poste hier noch mal den Schnipsel:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# man beachte das rename nicht direkt aus os importiert wird.
from werkzeug.posixemulation import rename

    def save(self, session):
        fn = self.get_session_filename(session.sid)
        # hier wird eben atomar eine Datei erzeugt
        fd, tmp = tempfile.mkstemp(suffix=_fs_transaction_suffix,
                                   dir=self.path)
        f = os.fdopen(fd, 'wb')
        try:
            dump(dict(session), f, HIGHEST_PROTOCOL)
        finally:
            f.close()
        try:
            # und hier wird das ganze dann passend umbenannt.
            # wenn Du oben guckst, siehst Du dass rename() intern definiert ist
            # s. o.
            rename(tmp, fn)
            os.chmod(fn, self.mode)
        except (IOError, OSError):
            pass

Link

Du kannst Dir den MonkeyPatch in dem Modul ja mal angucken. Man erkennt dort, dass er nur im Falle von NT basierten OS benötigt wird.

So, ich hoffe Du erkennst nun den Sinn dahinter, dass wir bereits auf Seite eins nach wenigen Posts auf werkzeug hingewiesen haben 😉

Glocke

(Themenstarter)
Avatar von Glocke

Anmeldungsdatum:
1. März 2009

Beiträge: 880

Wohnort: Thüringen

den sinn habe ich schon lange erkannt, aber mir ging es um das (mit eurer hilfe) eigene herangehen an das problem. code kopieren wäre das einfachste gewesen, richtig. dann hätte ich keine probleme und wir wären nicht schon auf seite 3. aber mir gehts halt darum selber mir gedanken zu machen - egal ob ich zum schluss bei was sehr ähnlichen rauskomme oder nicht. es ist einfach der wille nach erfahrungssammlung bzgl. problemlösung.

das problem was sich mir stellt (vllt auch nur denkfehler):

  • meine sid ist x, ich erstelle eine tempfile mit xy.dat

  • ein anderer prozess hat auch die sid x und erstellt xz.dat

  • jetzt bin ich vor dem anderen prozess mit speichern und umbenennen dran und habe meine x.dat fertig

    • der andere prozess speichert seine daten, rename und überschreibt damit meine. daten von meinem prozess weg.

  • oder es dauert mein prozess warum auch immer länger und der andere prozess speichert und benennt als erstes um

    • dann heißt seine file x.dat

    • jetzt komm ich und speichere meine daten und benenne um. rename überschreibt ohne rückfrage. die alte x.dat wird mit der neuen x.dat überschrieben - daten des zweiten prozesses weg.

nicht schön oder habe ich da nen denkfehler