Python: Jak stworzyć unikalną nazwę pliku?

95

Mam formularz internetowy w języku Python z dwiema opcjami - przesyłanie plików i obszar tekstowy . Muszę pobrać wartości z każdego z nich i przekazać je do innego programu wiersza poleceń. Mogę łatwo przekazać nazwę pliku z opcjami przesyłania pliku, ale nie jestem pewien, jak przekazać wartość pola tekstowego.

Myślę, że muszę:

  1. Wygeneruj unikalną nazwę pliku
  2. Utwórz plik tymczasowy o tej nazwie w katalogu roboczym
  3. Zapisz wartości przekazane z textarea do pliku tymczasowego
  4. Uruchom program wiersza poleceń z wnętrza mojego modułu Pythona i przekaż mu nazwę pliku tymczasowego

Nie wiem, jak wygenerować unikalną nazwę pliku. Czy ktoś może mi dać kilka wskazówek, jak wygenerować unikalną nazwę pliku? Wszelkie algorytmy, sugestie i wiersze kodu są mile widziane.

Dzięki za troskę

MysticCodes
źródło
1
Zredagowałem Twoje pytanie, aby było jaśniejsze. Daj mi znać, jeśli zinterpretowałem coś nieprawidłowo!
culix

Odpowiedzi:

147

Nie sądziłem, że twoje pytanie było bardzo jasne, ale jeśli potrzebujesz tylko unikalnej nazwy pliku ...

import uuid

unique_filename = str(uuid.uuid4())
EnigmaCurry
źródło
Przepraszam, pracuję na platformie Windows, więc nie wiem, jak obsługiwać podproces
MysticCodes
uuid wydaje się tworzyć długi, unikalny ciąg. Nie sądzę, żeby lepiej było mieć nazwę pliku z długim ciągiem znaków i UUID, () w nim.
MysticCodes
6
Myślę, że uuid.uuid4().hexbyłby lepszym wyborem, zobacz szczegóły tutaj .
Gray Li,
4
@ToloPalmer: Bardziej prawdopodobne jest, że procesor komputera ma błąd przetwarzania, który powoduje załadowanie niewłaściwego pliku, niż wygenerowany identyfikator UUID koliduje z jakąkolwiek istniejącą wartością. UUID tworzy unikalną nazwę w modelu obliczeń, który rozumie, że nie wszystkie obliczenia są czystą matematyką.
GManNickG,
2
Pardon mojej niewiedzy starego komentarza ... Rzeczywiście nie jest wyjątkowy, ale bardzo mało prawdopodobne, zderzają, więc dobry wybór;)
Tolo Palmer
51

Jeśli chcesz tworzyć pliki tymczasowe w Pythonie, w standardowych bibliotekach Pythona znajduje się moduł o nazwie tempfile . Jeśli chcesz uruchomić inne programy do obsługi pliku, użyj tempfile.mkstemp (), aby utworzyć pliki i os.fdopen (), aby uzyskać dostęp do deskryptorów plików, które daje mkstemp ().

Nawiasem mówiąc, mówisz, że uruchamiasz polecenia z programu w języku Python? Prawie na pewno powinieneś używać modułu podprocesu .

Możesz więc całkiem wesoło napisać kod, który wygląda następująco:

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)

Po uruchomieniu tego catpolecenia powinieneś stwierdzić, że polecenie działało doskonale, ale plik tymczasowy został usunięty z finallybloku. Należy pamiętać, że mają usunąć plik tymczasowy że mkstemp () zwraca się - biblioteka nie ma możliwości dowiedzenia się, kiedy jesteś z nim zrobić!

(Edycja: przypuszczałem, że NamedTemporaryFile zrobił dokładnie to, czego szukasz, ale może to nie być tak wygodne - plik zostanie usunięty natychmiast po zamknięciu obiektu pliku tymczasowego, a inne procesy otworzą plik przed jego zamknięciem nie będzie działać na niektórych platformach, zwłaszcza w systemie Windows. Przepraszamy, nie powiodło się z mojej strony).

Richard Barrell
źródło
użycie NamedTemporaryFile jest prawdopodobnie tym, czego chcą (chyba że chcą, aby pozostało na serwerze, a następnie mogą użyć „tempfile.NamedTemporaryFile (delete = False)”)
Terence Honles
Czy mogę sprawić, aby nazwa pliku tymczasowego była również niepowtarzalna? więc mogę zapisać go później, gdy podproces zostanie zakończony z unikalną nazwą
MysticCodes
@Terence Honles: Początkowo sugerowałem tempfile.NamedTemporaryFile (), ale tak naprawdę nie możesz tego użyć do tworzenia plików tymczasowych, do których inne procesy będą miały dostęp w systemie Windows. NamedTemporaryFile (delete = False) z pewnością jest jednak czystszy . @ user343934: tempfile.mkstemp () gwarantuje, że przy każdym wywołaniu otrzymasz unikalną nazwę - generuje nazwy losowo i używa funkcji systemu operacyjnego (O_EXCL, jeśli się zastanawiasz), aby uniknąć kolizji.
Richard Barrell
wow, nie wiedziałem, że to nie działa w
systemie
@Terence Honles: NamedTemporaryFile () w rzeczywistości nie zawodzi w systemie Windows (o ile wiem), ale nie można zamknąć pliku bez jego usunięcia, a (jak rozumiem semantykę plików w systemie Windows) żaden inny program nie może otworzyć plik, gdy masz go otwarty. Mogę się mylić; semantyka współdzielenia pliku przez wiele procesów w systemie Windows mogła ulec zmianie od czasu ostatniego sprawdzenia.
Richard Barrell
32

uuidModuł byłby to dobry wybór, wolę używać uuid.uuid4().hexjako przypadkowej nazwy pliku, ponieważ będzie to powrót ciąg szesnastkowy bez kresek .

import uuid
filename = uuid.uuid4().hex

Wyniki powinny wyglądać następująco:

>>> import uuid
>>> uuid.uuid()
UUID('20818854-3564-415c-9edc-9262fbb54c82')
>>> str(uuid.uuid4())
'f705a69a-8e98-442b-bd2e-9de010132dc4'
>>> uuid.uuid4().hex
'5ad02dfb08a04d889e3aa9545985e304'  # <-- this one
Gray Li
źródło
1
Jaki jest problem z myślnikami?
David Lopez,
15

Może potrzebujesz unikalnego pliku tymczasowego?

import tempfile

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

print f.name
f.close()

f jest plikiem otwartym. delete=Falseoznacza, że ​​nie usuwaj pliku po zamknięciu.

Jeśli potrzebujesz kontroli nad nazwą pliku, istnieją argumenty opcjonalne prefix=...i suffix=...przyjmujące ciągi. Zobacz https://docs.python.org/3/library/tempfile.html .

Роман Буртник
źródło
Jest to świetne rozwiązanie, jeśli nie musisz kontrolować nazwy pliku.
hiwaylon
1
Powinien to być tmpfile.NamedTemporaryFile, a nie tylko NamedTemporaryFile.
user1993015
w+bjest wartością domyślną mode. tempfileWadą korzystania z dowolnej funkcji są niepoprawne uprawnienia dostępu do plików: tempfiledokumenty używane os.O_TMPFILEjako maska, ale normalne tworzenie plików jest zgodne os.umask().
m8mble
8

Możesz użyć modułu datetime

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

Zauważ, że: używam, replaceponieważ dwukropki nie są dozwolone w nazwach plików w wielu systemach operacyjnych.

To wszystko, za każdym razem otrzymasz unikalną nazwę pliku.

Nimish Agrawal
źródło
2
Chyba że nazwy plików są tworzone bezpośrednio po sobie (np. W pętli). Wtedy są takie same.
skjerns
1

Trafiłem na to pytanie i dodam moje rozwiązanie dla tych, którzy mogą szukać czegoś podobnego. Moje podejście polegało na utworzeniu losowej nazwy pliku ze asciiznaków. Będzie wyjątkowy z dużym prawdopodobieństwem.

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)
behzad.nouri
źródło
1
Oczywista odpowiedź na to pytanie dotyczy pakietu uuid. Jednak mój serwer docelowy ma python 2.4, nie ma pakietu uuid, a aktualizacja nie została autoryzowana przez właściciela serwera z powodu niezgodności starszego oprogramowania, więc ta odpowiedź działa dla mnie.
Alberto Gaona
1
Szczególnie podoba mi się ta odpowiedź: można ją łatwo dostosować do specyfikacji projektu.
swdev
1
1) Nie ma powodu, aby używać tutaj rekurencji, zwłaszcza nieograniczonej. 2) Pomiędzy momentem path.exists()powrotu Falsea faktycznym otwarciem pliku przez konsumenta istnieje sytuacja wyścigu .
Jonathon Reinhart
1

Można to zrobić za pomocą unikalnej funkcji w module ufp.path .

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

jeśli istnieje bieżąca ścieżka, plik „test.ext”. ufp.path.unique function return './test (d1) .ext'.

c2o93y50
źródło
6
ufp jest częścią drupal? nie jest to standardowy moduł
endolit
1

Aby utworzyć unikalną ścieżkę do pliku, jeśli istnieje, użyj pakietu losowego, aby wygenerować nową nazwę ciągu dla pliku. Możesz odnieść się do poniższego kodu dla tego samego.

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

Teraz możesz użyć tej ścieżki do odpowiedniego utworzenia pliku.

RoboMex
źródło
1

Jeśli potrzebujesz krótkich, unikalnych identyfikatorów jako nazwy pliku, spróbuj shortuuid, shortuuid używa małych i wielkich liter oraz cyfr i usuwa podobnie wyglądające znaki, takie jak l, 1, I, O i 0.

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

w porównaniu do

>>> import uuid
>>> unique_filename = str(uuid.uuid4())
>>> len(unique_filename)
36
>>> unique_filename
'2d303ad1-79a1-4c1a-81f3-beea761b5fdf'
Milind Deore
źródło