Python: Wie erstelle ich einen eindeutigen Dateinamen?


91

Ich habe ein Python-Webformular mit zwei Optionen - Datei-Upload und Textbereich . Ich muss die Werte von jedem nehmen und sie an ein anderes Befehlszeilenprogramm übergeben. Ich kann den Dateinamen leicht mit Optionen zum Hochladen von Dateien übergeben, bin mir jedoch nicht sicher, wie ich den Wert des Textbereichs übergeben soll.

Ich denke, was ich tun muss, ist:

  1. Generieren Sie einen eindeutigen Dateinamen
  2. Erstellen Sie eine temporäre Datei mit diesem Namen im Arbeitsverzeichnis
  3. Speichern Sie die vom Textbereich übergebenen Werte in der temporären Datei
  4. Führen Sie das Befehlszeilenprogramm in meinem Python-Modul aus und übergeben Sie ihm den Namen der temporären Datei

Ich bin nicht sicher, wie ich einen eindeutigen Dateinamen generieren soll. Kann mir jemand Tipps geben, wie man einen eindeutigen Dateinamen generiert? Alle Algorithmen, Vorschläge und Codezeilen sind willkommen.

Dank für Ihr Interesse


1
Ich habe Ihre Frage bearbeitet, um sie klarer zu machen. Lassen Sie mich wissen, wenn ich etwas falsch interpretiert habe!
Culix

Antworten:


141

Ich dachte nicht, dass Ihre Frage sehr klar war, aber wenn Sie nur einen eindeutigen Dateinamen benötigen ...

import uuid

unique_filename = str(uuid.uuid4())

Tut mir leid, ich arbeite an der Windows-Plattform, also weiß ich nicht, wie ich mit
Unterprozessen

uuid scheint eine lange, eindeutige Zeichenfolge zu erstellen. Ich denke nicht, dass es besser ist, einen Dateinamen mit einer langen Zeichenfolge und UUID () zu haben.
MysticCodes

6
Ich denke, uuid.uuid4().hexwäre eine bessere Wahl, siehe Details hier .
Gray Li

4
@ToloPalmer: Es ist wahrscheinlicher, dass die CPU Ihres Computers einen Verarbeitungsfehler aufweist, der dazu führt, dass die falsche Datei geladen wird, als dass eine generierte UUID mit einem vorhandenen Wert kollidiert. UUID erzeugt einen eindeutigen Namen in einem Computermodell, das versteht, dass nicht alle Berechnungen reine Mathematik sind.
GManNickG

2
Verzeihen Sie meine Unwissenheit alten Kommentar ... In der Tat ist nicht einzigartig, aber sehr unwahrscheinlich zu kollidieren, so gute Wahl;)
Tolo Palmer

50

Wenn Sie temporäre Dateien in Python erstellen möchten, gibt es in den Standardbibliotheken von Python ein Modul namens tempfile . Wenn Sie andere Programme starten möchten, um die Datei zu bearbeiten, verwenden Sie tempfile.mkstemp (), um Dateien zu erstellen, und os.fdopen (), um auf die von mkstemp () bereitgestellten Dateideskriptoren zuzugreifen.

Sie sagen übrigens, Sie führen Befehle aus einem Python-Programm aus? Sie sollten mit ziemlicher Sicherheit das Unterprozessmodul verwenden .

Sie können also ganz fröhlich Code schreiben, der so aussieht:

import subprocess
import tempfile
import os

(fd, filename) = tempfile.mkstemp()
try:
    tfile = os.fdopen(fd, "w")
    tfile.write("Hello, world!\n")
    tfile.close()
    subprocess.Popen(["/bin/cat", filename]).wait()        
finally:
    os.remove(filename)

Wenn Sie dies ausführen, sollten Sie feststellen, dass der catBefehl einwandfrei funktioniert hat, die temporäre Datei jedoch im finallyBlock gelöscht wurde . Beachten Sie, dass Sie haben die temporäre Datei zu löschen , dass mkstemp () selbst zurück - die Bibliothek keine Möglichkeit hat , zu wissen , wann Sie mit ihm fertig sind!

(Bearbeiten: Ich hatte angenommen, dass NamedTemporaryFile genau das getan hat, wonach Sie suchen, aber das ist möglicherweise nicht so praktisch - die Datei wird sofort gelöscht, wenn das temporäre Dateiobjekt geschlossen wird, und andere Prozesse öffnen die Datei, bevor Sie sie schließen funktioniert auf einigen Plattformen nicht, insbesondere unter Windows. Entschuldigung, meinerseits scheitern.)


Die Verwendung von NamedTemporaryFile ist wahrscheinlich das, was sie wollen (es sei denn, sie möchten, dass es auf dem Server bleibt, und dann können sie "tempfile.NamedTemporaryFile (delete = False)" verwenden)
Terence Honles

Kann ich diesen temporären Dateinamen auch eindeutig machen? so kann ich es später speichern, wenn der
Unterprozess

@Terence Honles: Ich hatte ursprünglich tempfile.NamedTemporaryFile () vorgeschlagen, aber Sie können das nicht wirklich verwenden, um temporäre Dateien zu erstellen, auf die andere Prozesse unter Windows zugreifen können. NamedTemporaryFile (delete = False) ist jedoch sicherlich sauberer . @ user343934: tempfile.mkstemp () gibt Ihnen garantiert bei jedem Aufruf einen eindeutigen Namen - es generiert die Namen zufällig und verwendet die Betriebssystemfunktionen (O_EXCL, wenn Sie sich fragen), um Kollisionen zu vermeiden.
Richard Barrell

Wow, ich wusste nicht, dass es unter Windows nicht funktioniert ... Fehler :( ... Ich denke, das ist gut zu wissen
Terence Honles

@Terence Honles: NamedTemporaryFile () schlägt unter Windows nicht fehl (soweit ich weiß), aber Sie können Dateien nicht schließen, ohne sie auch zu löschen, und (wie ich die Dateisemantik unter Windows verstehe) kann kein anderes Programm das öffnen Datei, während Sie es geöffnet haben. Ich könnte falsch liegen; Die Semantik für mehrere Prozesse, die eine Datei unter Windows gemeinsam nutzen, hat sich möglicherweise seit meiner letzten Überprüfung geändert.
Richard Barrell

30

Das uuidModul wäre eine gute Wahl. Ich bevorzuge die Verwendung uuid.uuid4().hexals zufälliger Dateiname, da es eine hexadezimale Zeichenfolge ohne Bindestriche zurückgibt .

import uuid
filename = uuid.uuid4().hex

Die Ausgänge sollten folgendermaßen aussehen:

>>> import uuid
>>> uuid.uuid()
UUID('20818854-3564-415c-9edc-9262fbb54c82')
>>> str(uuid.uuid4())
'f705a69a-8e98-442b-bd2e-9de010132dc4'
>>> uuid.uuid4().hex
'5ad02dfb08a04d889e3aa9545985e304'  # <-- this one

Was ist das Problem mit Strichen?
David Lopez

14

Vielleicht benötigen Sie eine eindeutige temporäre Datei?

import tempfile

f = tempfile.NamedTemporaryFile(mode='w+b', delete=False)

print f.name
f.close()

f ist geöffnete Datei. delete=Falsebedeutet, dass die Datei nach dem Schließen nicht gelöscht wird.

Wenn Sie die Kontrolle über den Namen der Datei benötigen, gibt es optionale Argumente prefix=...und suffix=...Argumente, die Zeichenfolgen annehmen. Siehe https://docs.python.org/3/library/tempfile.html .


Dies ist ideal, wenn Sie den Namen der Datei nicht steuern müssen.
Hiwaylon

1
Es sollte tmpfile.NamedTemporaryFile sein, nicht nur NamedTemporaryFile.
user1993015

w+bist die Standardeinstellung mode. Die Verwendung von tempfileFunktionen hat den Nachteil falscher Dateizugriffsberechtigungen: tempfileDokumente, die os.O_TMPFILEals Maske verwendet werden sollen, aber bei der normalen Dateierstellung os.umask().
m8mble

8

Sie können das datetime- Modul verwenden

import datetime
uniq_filename = str(datetime.datetime.now().date()) + '_' + str(datetime.datetime.now().time()).replace(':', '.')

Beachten Sie Folgendes: Ich verwende, replaceda die Doppelpunkte in vielen Betriebssystemen in Dateinamen nicht zulässig sind.

Das ist es, dies gibt Ihnen jedes Mal einen eindeutigen Dateinamen.


2
Es sei denn, die Dateinamen werden unmittelbar nacheinander erstellt (z. B. in einer Schleife). Dann sind sie gleich.
Skjerns

1

Ich bin auf diese Frage gestoßen und werde meine Lösung für diejenigen hinzufügen, die nach etwas Ähnlichem suchen. Mein Ansatz war nur, aus asciiZeichen einen zufälligen Dateinamen zu machen . Es wird mit einer guten Wahrscheinlichkeit einzigartig sein.

from random import sample
from string import digits, ascii_uppercase, ascii_lowercase
from tempfile import gettempdir
from os import path

def rand_fname(suffix, length=8):
    chars = ascii_lowercase + ascii_uppercase + digits

    fname = path.join(gettempdir(), 'tmp-'
                + ''.join(sample(chars, length)) + suffix)

    return fname if not path.exists(fname) \
                else rand_fname(suffix, length)

1
Die offensichtliche Antwort auf die Frage hatte mit dem UUID-Paket zu tun. Mein Zielserver verfügt jedoch über Python 2.4, kein UUID-Paket, und das Upgrade wurde vom Serverbesitzer aufgrund von Inkompatibilitäten mit älterer Software nicht autorisiert. Daher funktioniert diese Antwort für mich.
Alberto Gaona

1
Diese Antwort gefällt mir besonders gut: Sie kann leicht an die Projektspezifikationen angepasst werden.
Swdev

1
1) Es gibt hier keinen Grund, Rekursion zu verwenden, insbesondere unbegrenzt. 2) Zwischen der path.exists()Rückkehrzeit Falseund der Zeit, zu der ein Verbraucher die Datei tatsächlich öffnet, besteht eine Race-Bedingung .
Jonathon Reinhart

1

Dies kann mit der eindeutigen Funktion im Modul ufp.path erfolgen .

import ufp.path
ufp.path.unique('./test.ext')

Wenn der aktuelle Pfad in der Datei 'test.ext' vorhanden ist. Die Funktion ufp.path.unique gibt './test (d1) .ext' zurück.


6
ufp ist ein teil von drupal? kein Standardmodul
Endolith

1

Verwenden Sie zum Erstellen eines eindeutigen Dateipfads, falls vorhanden, ein zufälliges Paket, um einen neuen Zeichenfolgennamen für die Datei zu generieren. Sie können den folgenden Code für denselben verwenden.

import os
import random
import string

def getUniquePath(folder, filename):    
    path = os.path.join(folder, filename)
    while os.path.exists(path):
         path = path.split('.')[0] + ''.join(random.choice(string.ascii_lowercase) for i in range(10)) + '.' + path.split('.')[1]
    return path

Jetzt können Sie diesen Pfad verwenden, um eine entsprechende Datei zu erstellen.


0

Wenn Sie kurze eindeutige IDs als Dateinamen benötigen, versuchen Sie shortuuid, shortuuid verwendet Klein- und Großbuchstaben und Ziffern und entfernt ähnlich aussehende Zeichen wie l, 1, I, O und 0.

>>> import shortuuid
>>> shortuuid.uuid()
'Tw8VgM47kSS5iX2m8NExNa'
>>> len(ui)
22

verglichen mit

>>> import uuid
>>> unique_filename = str(uuid.uuid4())
>>> len(unique_filename)
36
>>> unique_filename
'2d303ad1-79a1-4c1a-81f3-beea761b5fdf'
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.