tempfile.mkstemp: Wie auf die Datei zugreifen?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
ChrisGTJ
User
Beiträge: 105
Registriert: Mittwoch 22. August 2007, 15:45

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
ChrisGTJ
User
Beiträge: 105
Registriert: Mittwoch 22. August 2007, 15:45

Bin ich deppert? Entschuldigt, daß dieses Posting im falschen Forum gelandet ist. Würde es mal bitte jemand verschieben? :oops:

Danke,

Christoph
Benutzeravatar
Toni83
User
Beiträge: 125
Registriert: Donnerstag 28. Juli 2005, 10:53

Code: Alles auswählen

import tempfile
tempfile.mkstemp(".mkstemp","temp","C:/")
Dies zum anlegen der Datei!

Code: Alles auswählen

f=file("C:/temp.mkstemp","r+")
f.read()
Und dies zum lesen der Daten. Danach kannst split oder strip anwenden,...
Für das Schreiben einfach statt "r+", "w+" schreiben und dann f.write()

Gruß,
Toni
lunar

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``.
ChrisGTJ
User
Beiträge: 105
Registriert: Mittwoch 22. August 2007, 15:45

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
ChrisGTJ
User
Beiträge: 105
Registriert: Mittwoch 22. August 2007, 15:45

....ah halt, wer liest, ist klar im Vorteil...

os.fdopen() öffnet also eine Datei, auf die der Descriptor zeigt.

Aber:
Die Datei ist laut Doku schon geöffnet. Habe ich was falsch verstanden?
lunar

``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.
ChrisGTJ
User
Beiträge: 105
Registriert: Mittwoch 22. August 2007, 15:45

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
lunar

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.
Hältst du es tatsächlich für eine gute Idee, *eine* Datei für *mehrere* Aufgaben zu verwenden?

Ich würde ja einfach mehrere temporäre Dateien erzeugen, je eine für eine bestimmte Aufgabe.
Also doch einmal seek(...) um wieder vom Anfang lesen zu können, oder?
Wenn du so willst, ja.
BlackJack

@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.
lunar

Explizit steht das nirgendwo, da hast du schon recht. Ich schließe das allein aus folgendem:
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.
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.
BlackJack

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()`.
ChrisGTJ
User
Beiträge: 105
Registriert: Mittwoch 22. August 2007, 15:45

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
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

IMHO kannst du auch alles im Speicher auspacken und brauchst nicht zwingend eine Datei. Kommt darauf an, wie groß die Daten sind...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
ChrisGTJ
User
Beiträge: 105
Registriert: Mittwoch 22. August 2007, 15:45

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...
Kann ich, nur brauche ich eine Datei für die nachfolgende Bearbeitung, da es eben eine dateibasierte Schnittstelle ist.

Christoph
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Wenn die Bibliothek file-like-Objects verwendet, dann kannst du StringIO verwenden.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
ChrisGTJ
User
Beiträge: 105
Registriert: Mittwoch 22. August 2007, 15:45

Leonidas hat geschrieben:Wenn die Bibliothek file-like-Objects verwendet, dann kannst du StringIO verwenden.
Hm, aber die Bibothek möchte doch eine Datei öffnen, ich benutze ctypes.create_string_buffer().

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
lunar

ChrisGTJ hat geschrieben:
Leonidas hat geschrieben:Wenn die Bibliothek file-like-Objects verwendet, dann kannst du StringIO verwenden.
Hm, aber die Bibothek möchte doch eine Datei öffnen, ich benutze ctypes.create_string_buffer().
Welche Bibliothek ist das denn?
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.
Du öffnest die Datei nicht nochmal, du erzeugst nur ein Dateiobjekt aus dem Dateideskriptor. Das habe ich dir aber schon mal gesagt...
ChrisGTJ
User
Beiträge: 105
Registriert: Mittwoch 22. August 2007, 15:45

lunar hat geschrieben:
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.
Du öffnest die Datei nicht nochmal, du erzeugst nur ein Dateiobjekt aus dem Dateideskriptor. Das habe ich dir aber schon mal gesagt...
Ups... :oops: , Du hast recht. aber mal ehrlich: fdOPEN suggeriert doch ein öffnen, oder?

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
Antworten