Ein Problem ist, dass es in Ihrem obigen Code eine Race Condition gibt, da es eine Lücke zwischen dem Testen auf Existenz und dem Erstellen der Datei gibt. Es kann Sicherheitsbedenken geben (denken Sie daran, dass jemand einen Symlink böswillig in eine sensible Datei einfügt, die er nicht überschreiben könnte, aber Ihr Programm könnte mit einem höheren Privileg ausgeführt werden). Angriffe wie diese sind Gründe, warum os.tempnam () sind veraltet.
Um es zu umgehen, ist der beste Ansatz, die Datei tatsächlich so zu erstellen, dass Sie eine Ausnahme erhalten, wenn sie fehlschlägt, und bei Erfolg das tatsächlich geöffnete Dateiobjekt zurückgibt. Dies kann mit den os.open-Funktionen auf der unteren Ebene erfolgen, indem die beiden Flags os.O_CREAT und os.O_EXCL übergeben werden. Nach dem Öffnen geben Sie die tatsächliche Datei (und optional den Dateinamen) zurück, die Sie erstellt haben. Zum Beispiel, hier ist der Code geändert, diesen Ansatz zu verwenden (eine (Datei, Dateiname) Tupel Rückkehr):
def unique_file(file_name):
counter = 1
file_name_parts = os.path.splitext(file_name) # returns ('/path/file', '.ext')
while 1:
try:
fd = os.open(file_name, os.O_CREAT | os.O_EXCL | os.O_RDRW)
return os.fdopen(fd), file_name
except OSError:
pass
file_name = file_name_parts[0] + '_' + str(counter) + file_name_parts[1]
counter += 1
[Bearbeiten] Eigentlich eine bessere Art und Weise, die die oben genannten Fragen für Sie, wahrscheinlich handhaben ist um das Tempfilemodul zu verwenden, obwohl Sie einige Kontrolle über die Benennung verlieren können.Hier ist ein Beispiel, es zu benutzen (eine ähnliche Schnittstelle zu halten):
def unique_file(file_name):
dirname, filename = os.path.split(file_name)
prefix, suffix = os.path.splitext(filename)
fd, filename = tempfile.mkstemp(suffix, prefix+"_", dirname)
return os.fdopen(fd), filename
>>> f, filename=unique_file('/home/some_dir/foo.txt')
>>> print filename
/home/some_dir/foo_z8f_2Z.txt
Der einzige Nachteil bei diesem Ansatz ist, dass Sie immer einen Dateinamen mit einigen zufälligen Zeichen in ihm bekommen, da es kein Versuch ist eine unveränderte Datei zu erstellen (/home/some_dir/foo.txt) zuerst. Sie können auch tempfile.TemporaryFile und NamedTemporaryFile sehen, die das obige tun und auch automatisch von der Festplatte löschen, wenn sie geschlossen werden.
Ja, das ist The_Right_Way, es zu tun. Ich wünschte, ich könnte mich selbst abwandeln und deine Antwort an die Spitze setzen! –
Kleiner Tippfehler: das sollte "os.O_RDWR" statt "os.O_RDRW" sein – tremby