Der beste Weg, um zufällige Dateinamen in Python zu generieren

95

Was ist in Python eine gute oder beste Möglichkeit, zufälligen Text zu generieren, um einer Datei (einem Namen), die ich auf einem Server speichere, vorangestellt zu werden, um sicherzustellen, dass sie nicht überschrieben wird? Danke dir!

Zallarak
quelle

Antworten:

109

Python verfügt über Funktionen zum Generieren temporärer Dateinamen (siehe http://docs.python.org/library/tempfile.html) . Zum Beispiel:

In [4]: import tempfile

Jeder Aufruf von tempfile.NamedTemporaryFile()führt zu einer anderen temporären Datei, auf deren Namen mit dem .nameAttribut zugegriffen werden kann, z.

In [5]: tf = tempfile.NamedTemporaryFile()
In [6]: tf.name
Out[6]: 'c:\\blabla\\locals~1\\temp\\tmptecp3i'

In [7]: tf = tempfile.NamedTemporaryFile()
In [8]: tf.name
Out[8]: 'c:\\blabla\\locals~1\\temp\\tmpr8vvme'

Sobald Sie den eindeutigen Dateinamen haben, kann er wie jede normale Datei verwendet werden. Hinweis : Standardmäßig wird die Datei beim Schließen gelöscht . Wenn der deleteParameter jedoch False ist, wird die Datei nicht automatisch gelöscht.

Vollständiger Parametersatz:

tempfile.NamedTemporaryFile([mode='w+b'[, bufsize=-1[, suffix=''[, prefix='tmp'[, dir=None[, delete=True]]]]]])

Es ist auch möglich, das Präfix für die temporäre Datei anzugeben (als einen der verschiedenen Parameter, die während der Dateierstellung angegeben werden können):

In [9]: tf = tempfile.NamedTemporaryFile(prefix="zz")
In [10]: tf.name
Out[10]: 'c:\\blabla\\locals~1\\temp\\zzrc3pzk'

Weitere Beispiele für die Arbeit mit temporären Dateien finden Sie hier

Levon
quelle
1
Würden diese Dateien beim nächsten Neustart meines Computers gelöscht?
HelloWorld
14
Das Problem bei dieser Lösung ist, dass nicht nur ein Dateiname generiert wird, sondern auch eine Datei, die bereits geöffnet ist. Wenn Sie einen temporären Dateinamen für eine neue, noch nicht vorhandene Datei benötigen (z. B. als Ausgabe eines OS-Befehls), reicht dies nicht aus. In diesem Fall können Sie so etwas wie str (uuid.uuid4 ()) ausführen.
Luca
@ Luca Vielen Dank für den zusätzlichen Kommentar, der nützlich ist und als zukünftige Referenz dient. OP gab jedoch eindeutig an, dass er / sie eine Datei speichern wollte und sie daher öffnen muss, sodass diese Lösung dies vorsieht.
Levon
Es hängt davon ab, ob. Vielleicht braucht er den Namen, um einen geeigneten Serveraufruf zu erstellen. Nicht sicher. In jedem Fall ist Ihre Antwort sicherlich der häufigste Fall.
Luca
104

Sie können das UUID-Modul zum Generieren einer zufälligen Zeichenfolge verwenden:

import uuid
filename = str(uuid.uuid4())

Dies ist eine gültige Wahl, da es äußerst unwahrscheinlich ist , dass ein UUID- Generator einen doppelten Bezeichner (in diesem Fall einen Dateinamen) erzeugt:

Erst nachdem in den nächsten 100 Jahren 1 Milliarde UUIDs pro Sekunde generiert wurden, liegt die Wahrscheinlichkeit, nur ein Duplikat zu erstellen, bei etwa 50%. Die Wahrscheinlichkeit eines Duplikats würde etwa 50% betragen, wenn jeder Mensch auf der Erde 600 Millionen UUIDs besitzt.

Óscar López
quelle
16
Dies ist auch sehr nützlich, wenn Sie einen eindeutigen Dateinamen möchten, diesen aber noch nicht erstellen möchten.
Prof. Falken
14
Oder verwenden Sie uuid.uuid4().hex, um eine Hex-Zeichenfolge ohne Bindestriche ( -) zu erhalten.
Rockallite
17

Ein gängiger Ansatz besteht darin, dem Dateinamen einen Zeitstempel als Präfix / Suffix hinzuzufügen, um eine zeitliche Beziehung zur Datei herzustellen. Wenn Sie mehr Eindeutigkeit benötigen, können Sie dieser noch eine zufällige Zeichenfolge hinzufügen.

import datetime
basename = "mylogfile"
suffix = datetime.datetime.now().strftime("%y%m%d_%H%M%S")
filename = "_".join([basename, suffix]) # e.g. 'mylogfile_120508_171442'
moooeeeep
quelle
4
In einer Umgebung mit mehreren Threads ist eine mögliche Race-Bedingung in der Sequenz enthalten. 1. Test if file exists, 2. create file.Wenn ein anderer Prozess Ihren zwischen den Schritten 1 und 2 unterbricht und die Datei erstellt, überschreibt der Code bei Wiederaufnahme des Codes die Datei des anderen Prozesses.
Li-aung Yip
@ Li-aungYip Kann zusätzlich auch 6-8 zufällige Zeichenfolgen verwenden (falls 2 Dateien in derselben Sekunde generiert werden).
Bobobobo
@bobobobo: Oder Sie könnten das tempfileModul verwenden, das dies für Sie erledigt. :)
Li-aung Yip
Ich würde vorschlagen, Mikrosekunden hinzuzufügen, dh...strftime("%y%m%d_%H%M%S%f")
AstraSerg
8

Das OP forderte an, zufällige Dateinamen und keine zufälligen Dateien zu erstellen . Zeiten und UUIDs können kollidieren. Wenn Sie auf einem einzelnen Computer arbeiten (kein freigegebenes Dateisystem) und Ihr Prozess / Thread nicht auf sich selbst stampft, verwenden Sie os.getpid (), um Ihre eigene PID abzurufen und diese als Element eines eindeutigen Dateinamens zu verwenden. Andere Prozesse würden offensichtlich nicht die gleiche PID erhalten. Wenn Sie Multithread-fähig sind, rufen Sie die Thread-ID ab. Wenn Sie andere Aspekte Ihres Codes haben, in denen ein einzelner Thread oder Prozess mehrere verschiedene Tempfiles generieren kann, müssen Sie möglicherweise eine andere Technik verwenden. Ein fortlaufender Index kann funktionieren (wenn Sie ihn nicht so lange aufbewahren oder so viele Dateien verwenden, würden Sie sich über einen Rollover Gedanken machen). In diesem Fall würde es ausreichen, einen globalen Hash / Index für "aktive" Dateien beizubehalten.

Entschuldigen Sie die langwierige Erklärung, aber sie hängt von Ihrer genauen Verwendung ab.

Brad
quelle
8

Wenn Sie keinen Dateipfad benötigen, sondern nur die zufällige Zeichenfolge mit vordefinierter Länge, können Sie so etwas verwenden.

>>> import random
>>> import string

>>> file_name = ''.join(random.choice(string.ascii_lowercase) for i in range(16))
>>> file_name
'ytrvmyhkaxlfaugx'
4xy
quelle
7

Wenn Sie den ursprünglichen Dateinamen als Teil des neuen Dateinamens beibehalten möchten, können mithilfe von MD5-Hashes der aktuellen Zeit eindeutige Präfixe mit einheitlicher Länge generiert werden:

from hashlib import md5
from time import localtime

def add_prefix(filename):
    prefix = md5(str(localtime()).encode('utf-8')).hexdigest()
    return f"{prefix}_{filename}"

Aufrufe des add_prefix ('style.css') erzeugen eine Sequenz wie:

a38ff35794ae366e442a0606e67035ba_style.css
7a5f8289323b0ebfdbc7c840ad3cb67b_style.css
Aleš Kotnik
quelle
1
Um dies zu vermeiden: Unicode-Objekte müssen vor dem Hashing codiert werden. Ich habe in md5 (str (localtime ()). Codiert ('utf-8')) geändert. Hexdigest ()
PhoebeB
1
Beachten Sie, dass ein Hash einer beliebigen Art von Daten (einschließlich eines Zeitstempels) keine Eindeutigkeit für sich selbst gewährleistet (ebenso wenig wie eine zufällig ausgewählte Bytesequenz).
Peter O.
1

Fügen Sie hier meine zwei Cent hinzu:

In [19]: tempfile.mkstemp('.png', 'bingo', '/tmp')[1]
Out[19]: '/tmp/bingoy6s3_k.png'

Laut dem Python-Dokument für tempfile.mkstemp wird eine temporäre Datei auf möglichst sichere Weise erstellt. Bitte beachten Sie, dass die Datei nach diesem Aufruf vorhanden sein wird:

In [20]: os.path.exists(tempfile.mkstemp('.png', 'bingo', '/tmp')[1])
Out[20]: True
Shahins
quelle
1

Ich persönlich bevorzuge es, wenn mein Text nicht nur zufällig / einzigartig, sondern auch schön ist. Deshalb mag ich die Hashids-Bibliothek, die gut aussehenden zufälligen Text aus ganzen Zahlen generiert. Kann durch installiert werden

pip install hashids

Snippet:

import hashids
hashids = hashids.Hashids(salt="this is my salt", )
print hashids.encode(1, 2, 3)
>>> laHquq

Kurze Beschreibung:

Hashids ist eine kleine Open-Source-Bibliothek, die aus Zahlen kurze, eindeutige, nicht sequentielle IDs generiert.

user1767754
quelle
0
>>> import random
>>> import string    
>>> alias = ''.join(random.choice(string.ascii_letters) for _ in range(16))
>>> alias
'WrVkPmjeSOgTmCRG'

Sie können 'string.ascii_letters' in ein beliebiges Zeichenfolgenformat ändern, wenn Sie einen anderen Text generieren möchten, z. B. mobile NO, ID ... Geben Sie hier die Bildbeschreibung ein

Freman Zhang
quelle
0
import uuid
   imageName = '{}{:-%Y%m%d%H%M%S}.jpeg'.format(str(uuid.uuid4().hex), datetime.now())
Asad Farooq
quelle
1
Während dieser Code die Frage lösen kann, einschließlich einer Erklärung, wie und warum dies das Problem löst, würde dies wirklich dazu beitragen, die Qualität Ihres Beitrags zu verbessern, und wahrscheinlich zu mehr Up-Votes führen. Denken Sie daran, dass Sie in Zukunft die Frage für die Leser beantworten, nicht nur für die Person, die jetzt fragt. Bitte bearbeiten Sie Ihre Antwort, um Erklärungen hinzuzufügen und anzugeben, welche Einschränkungen und Annahmen gelten.
29огдан Опир
-1

Sie könnten das Zufallspaket verwenden:

import random
file = random.random()
anajem
quelle
file = str (random.random ())
anajem
Dies erzeugt Zufallszahlen, keinen zufälligen Text.
user1767754