Hallo Leute,
ich möchte eine Datei mit tempfile.mkstemp anlegen und sie benutzen, wie man eine Datei eben benutzt: Öffnen, schließen, schreiben und lesen. Die Frage ist nur: wie?
Die Doku sagt:
"mkstemp() returns a tuple containing an OS-level handle to an open file (as would be returned by os.open()) and the absolute pathname of that file, in that order."
Das heißt, ich habe den handle zu einer geöffneten Datei. Und nun?
- In welchem modus ist sie geöffnet?
- Wie mache ich aus einem handle (ein int!) eine file-Instanz, die ich benutzen kann?
Eigentlich möchte ich das Teil schließen und dann selbst wieder öffnen ("wb"), ich habe ja einen Namen und einen Pfad bekommen.
Gruß und Danke,
Christoph
tempfile.mkstemp: Wie auf die Datei zugreifen?
Code: Alles auswählen
import tempfile
tempfile.mkstemp(".mkstemp","temp","C:/")
Code: Alles auswählen
f=file("C:/temp.mkstemp","r+")
f.read()
Für das Schreiben einfach statt "r+", "w+" schreiben und dann f.write()
Gruß,
Toni
Dein Code funktioniert nicht. Der Name der Datei lautet nämlich nicht ``temp.mkstemp``, da ``mkstemp`` noch zufällige Zeichen hinzufügt, um den Namen eindeutig zu machen! Wenn du die Datei erneut öffnen willst, dann solltest du die Namen nehmen, der von ``mkstemp`` zurückgegeben wird.
Allerdings kannst du so eigentlich auch gleich auf ``mkstemp`` verzichten, da du eine Race Condition erzeugst.
Der Prozess kann zwischen ``mkstemp`` und ``file`` nämlich schlafen gelegt werden. In der Zwischenzeit kann ein anderer Prozess diese Datei löschen. Dann erzeugt der ``file``-Aufruf nämlich eine neue Datei! Das kann man dann wieder für Symlink-Attacken nutzen.
Entweder nutzt man ``os.fdopen``, um den von ``mkstemp`` zurückgegeben Dateideskriptor in ein Dateiobjekt zu verwandeln, oder – noch besser – man nimmt gleich ``tempfile.TemporaryFile`` oder tempfile.NamedTemporaryFile``.
Allerdings kannst du so eigentlich auch gleich auf ``mkstemp`` verzichten, da du eine Race Condition erzeugst.

Der Prozess kann zwischen ``mkstemp`` und ``file`` nämlich schlafen gelegt werden. In der Zwischenzeit kann ein anderer Prozess diese Datei löschen. Dann erzeugt der ``file``-Aufruf nämlich eine neue Datei! Das kann man dann wieder für Symlink-Attacken nutzen.
Entweder nutzt man ``os.fdopen``, um den von ``mkstemp`` zurückgegeben Dateideskriptor in ein Dateiobjekt zu verwandeln, oder – noch besser – man nimmt gleich ``tempfile.TemporaryFile`` oder tempfile.NamedTemporaryFile``.
Hallo,
danke erstmal für's Verschieben und für die Antworten.
Mein Ziel ist es eigentlich nur, eine Datei zu haben, die ich benutzen kann und die ich dann einfach wieder lösche, wenn ich sie nicht mehr brauche. Ich könnte natürlich einfach eine beliebige Datei an dem Ort, an dem ich gerade bin, öffnen, aber ich finde es ungeschickt, irgendwo im Filesystem eine Datei hinzulegen (vor allem, wenn ich an dem Ort vielleicht gar nicht schreiben darf).
In die Datei werden einige Daten geschrieben, die an anderer Stelle benutzt werden sollen, daher die Geschichte mit open und close. Ich könnte die Datei geöffnet lassen, müßte dann aber mit seek und so rumeiern.
Vor allem:
In der Doku steht, die Datei ist geöffnet nach mkstemp() und ich bekomme einen Handle darauf zurück. Wie mache ich aus dem handle ein Fileobjekt, das ich nutzen kann?
Die Symlinkattacke vernachlässige ich jetzt mal, laut Wikipedia (das macht ja schlau
) wird sie verhindert, indem eben mkstemp() benutzt wird.
Gruß,
Christoph
danke erstmal für's Verschieben und für die Antworten.
Mein Ziel ist es eigentlich nur, eine Datei zu haben, die ich benutzen kann und die ich dann einfach wieder lösche, wenn ich sie nicht mehr brauche. Ich könnte natürlich einfach eine beliebige Datei an dem Ort, an dem ich gerade bin, öffnen, aber ich finde es ungeschickt, irgendwo im Filesystem eine Datei hinzulegen (vor allem, wenn ich an dem Ort vielleicht gar nicht schreiben darf).
In die Datei werden einige Daten geschrieben, die an anderer Stelle benutzt werden sollen, daher die Geschichte mit open und close. Ich könnte die Datei geöffnet lassen, müßte dann aber mit seek und so rumeiern.
Vor allem:
In der Doku steht, die Datei ist geöffnet nach mkstemp() und ich bekomme einen Handle darauf zurück. Wie mache ich aus dem handle ein Fileobjekt, das ich nutzen kann?
Die Symlinkattacke vernachlässige ich jetzt mal, laut Wikipedia (das macht ja schlau

Gruß,
Christoph
``os.fdopen`` erzeugt aus einem Dateideskriptor ein Dateiobjekt, mehr nicht.
Die Symlink-Attacke wird durch mkstemp verhindert. Allerdings nur, wenn du den zurückgebenen Dateideskriptor zum Öffnen nutzt. Öffnest du die Datei erneut – wie von Toni83 vorgeschlagen – ist folgender Ablauf denkbar:
1. ``mkstemp`` öffnet die Datei
2. Der Kernel legt den Prozess schlafen
3. Ein anderer Prozess löscht die temporäre Datei und erzeugt stattdessen einen Symlink
4. Der Kernel weckt den Prozess wieder auf
5. ``file`` öffnet nun den Symlink und **nicht** mehr die in Schritt 1 per ``mkstemp`` geöffnete Datei!
Ich frage dich aber nochmal: Warum nutzt du nicht ``tempfile.TemporaryFile`` oder ``tempfile.NamedTemporaryFile``?
Diese Klassen übernehmen nicht nur das Öffnen der Dateideskriptoren, sondern sorgen beispielsweise auch dafür, dass die Datei beim Schließen automatisch gelöscht wird.
Die Symlink-Attacke wird durch mkstemp verhindert. Allerdings nur, wenn du den zurückgebenen Dateideskriptor zum Öffnen nutzt. Öffnest du die Datei erneut – wie von Toni83 vorgeschlagen – ist folgender Ablauf denkbar:
1. ``mkstemp`` öffnet die Datei
2. Der Kernel legt den Prozess schlafen
3. Ein anderer Prozess löscht die temporäre Datei und erzeugt stattdessen einen Symlink
4. Der Kernel weckt den Prozess wieder auf
5. ``file`` öffnet nun den Symlink und **nicht** mehr die in Schritt 1 per ``mkstemp`` geöffnete Datei!
Ich frage dich aber nochmal: Warum nutzt du nicht ``tempfile.TemporaryFile`` oder ``tempfile.NamedTemporaryFile``?
Diese Klassen übernehmen nicht nur das Öffnen der Dateideskriptoren, sondern sorgen beispielsweise auch dafür, dass die Datei beim Schließen automatisch gelöscht wird.
Hallo Lunar,
wie ich schon sagte: Ich will nicht mit seek() und so herumdoktoren.
Bei genauerem Lesen der Doku zu tempfile.TemporaryFile fällt mir auf, daß ich sie einfach geöffnet lassen könnte, das Fileobjekt weiterreichen könnte und sie am Ende wieder schließen könnte, damit wäre alles erledigt. Damit wäre auch das Problem der symlink-Attacke erledigt.
Also doch einmal seek(...) um wieder vom Anfang lesen zu können, oder?
Gruß,
Christoph
wie ich schon sagte: Ich will nicht mit seek() und so herumdoktoren.
Bei genauerem Lesen der Doku zu tempfile.TemporaryFile fällt mir auf, daß ich sie einfach geöffnet lassen könnte, das Fileobjekt weiterreichen könnte und sie am Ende wieder schließen könnte, damit wäre alles erledigt. Damit wäre auch das Problem der symlink-Attacke erledigt.
Also doch einmal seek(...) um wieder vom Anfang lesen zu können, oder?
Gruß,
Christoph
Hältst du es tatsächlich für eine gute Idee, *eine* Datei für *mehrere* Aufgaben zu verwenden?ChrisGTJ hat geschrieben:Bei genauerem Lesen der Doku zu tempfile.TemporaryFile fällt mir auf, daß ich sie einfach geöffnet lassen könnte, das Fileobjekt weiterreichen könnte und sie am Ende wieder schließen könnte, damit wäre alles erledigt. Damit wäre auch das Problem der symlink-Attacke erledigt.
Ich würde ja einfach mehrere temporäre Dateien erzeugen, je eine für eine bestimmte Aufgabe.
Wenn du so willst, ja.Also doch einmal seek(...) um wieder vom Anfang lesen zu können, oder?
@Lunar: Wo steht was von mehreren Aufgaben? Ich lese da nur das etwas in die Datei geschrieben werden soll und an anderer Stelle im Programm wieder ausgelesen werden soll.
Explizit steht das nirgendwo, da hast du schon recht. Ich schließe das allein aus folgendem:
Da er an dieser Stelle von ``seek`` spricht, liegt es ja offenbar in seinem Interesse, bereits geschriebene Daten wieder zu überschreiben. Das allerdings ergibt für mich wiederum nur dann Sinn, wenn das unterschiedliche Daten sind. In diesem Fall wären mehrere temporäre Dateien imho die bessere Lösung.In die Datei werden einige Daten geschrieben, die an anderer Stelle benutzt werden sollen, daher die Geschichte mit open und close. Ich könnte die Datei geöffnet lassen, müßte dann aber mit seek und so rumeiern.
Das lese ich da überhaupt nicht, im Gegenteil. Es sollen Daten *gelesen* werden. Und wenn nicht `open()` und `close()` verwendet werden, sondern die geöffnete Datei herum gereicht wird, *dann* braucht man `seek()`.
Wozu die Sache gebraucht wird:
Aus einem Gerät wird eine zip-Datei gelesen. Dieses Archiv enthält Dateien, von denen eine benötigt wird, aber auch (meist) nur einmal (da sind Infos zum Gerät drin, die sich unter Umständen ändern können, je nach Applikation, die auf dem Gerät läuft).
Ich muß das Zip also auspacken und die Infos lesen. Dazu verwende ich eine Bibliothek, die filebasiert arbeitet -> Ergo brauche ich ein temporäres File.
Danke für Eure Unterstützung
.
Gruß,
Christoph
Aus einem Gerät wird eine zip-Datei gelesen. Dieses Archiv enthält Dateien, von denen eine benötigt wird, aber auch (meist) nur einmal (da sind Infos zum Gerät drin, die sich unter Umständen ändern können, je nach Applikation, die auf dem Gerät läuft).
Ich muß das Zip also auspacken und die Infos lesen. Dazu verwende ich eine Bibliothek, die filebasiert arbeitet -> Ergo brauche ich ein temporäres File.
Danke für Eure Unterstützung

Gruß,
Christoph
Kann ich, nur brauche ich eine Datei für die nachfolgende Bearbeitung, da es eben eine dateibasierte Schnittstelle ist.jens hat geschrieben:IMHO kannst du auch alles im Speicher auspacken und brauchst nicht zwingend eine Datei. Kommt darauf an, wie groß die Daten sind...
Christoph
Hm, aber die Bibothek möchte doch eine Datei öffnen, ich benutze ctypes.create_string_buffer().Leonidas hat geschrieben:Wenn die Bibliothek file-like-Objects verwendet, dann kannst du StringIO verwenden.
os.fdopen() scheint der richtige Weg zu sein, aber wie ist das damit, daß die Datei schon geöffnet ist? Im Prinzip öffne ich doch eine schon geöffnete Datei... Ich kapier es nicht.
Gruß,
Christoph
Welche Bibliothek ist das denn?ChrisGTJ hat geschrieben:Hm, aber die Bibothek möchte doch eine Datei öffnen, ich benutze ctypes.create_string_buffer().Leonidas hat geschrieben:Wenn die Bibliothek file-like-Objects verwendet, dann kannst du StringIO verwenden.
Du öffnest die Datei nicht nochmal, du erzeugst nur ein Dateiobjekt aus dem Dateideskriptor. Das habe ich dir aber schon mal gesagt...os.fdopen() scheint der richtige Weg zu sein, aber wie ist das damit, daß die Datei schon geöffnet ist? Im Prinzip öffne ich doch eine schon geöffnete Datei... Ich kapier es nicht.
Ups...lunar hat geschrieben:Du öffnest die Datei nicht nochmal, du erzeugst nur ein Dateiobjekt aus dem Dateideskriptor. Das habe ich dir aber schon mal gesagt...os.fdopen() scheint der richtige Weg zu sein, aber wie ist das damit, daß die Datei schon geöffnet ist? Im Prinzip öffne ich doch eine schon geöffnete Datei... Ich kapier es nicht.

ctypes:
http://docs.python.org/lib/module-ctypes.html
14.14 ctypes -- A foreign function library for Python.
New in version 2.5.
ctypes is a foreign function library for Python. It provides C compatible data types, and allows to call functions in dlls/shared libraries. It can be used to wrap these libraries in pure Python.
Gruß,
Christoph