Python: Як створити унікальне ім'я файлу?


95

У мене є веб-форма python із двома варіантами - завантаження файлів та текстове поле . Мені потрібно взяти значення з кожного і передати їх іншій програмі командного рядка. Я можу легко передати ім'я файлу за допомогою опцій завантаження файлу, але я не впевнений, як передавати значення тексту.

Я думаю, що мені потрібно зробити, це:

  1. Створіть унікальне ім'я файлу
  2. Створіть тимчасовий файл із таким іменем у робочому каталозі
  3. Збережіть значення, передані з textarea, у тимчасовий файл
  4. Виконайте програму командного рядка всередині мого модуля python і передайте їй ім'я тимчасового файлу

Я не знаю, як створити унікальне ім'я файлу. Хто-небудь може дати мені кілька порад щодо створення унікального імені файлу? Будемо вдячні за будь-які алгоритми, пропозиції та рядки коду.

Дякую за вашу турботу


1
Я відредагував ваше запитання, щоб спробувати зробити його більш зрозумілим. Повідомте мене, якщо я щось неправильно витлумачив!
culix

Відповіді:


147

Я не думав, що ваше запитання було дуже чітким, але якщо вам потрібно лише унікальна назва файлу ...

import uuid

unique_filename = str(uuid.uuid4())

На жаль, я працюю на платформі Windows, тому не знаю, як обробляти підпроцес
MysticCodes

uuid, здається, створює довгий унікальний рядок. Я не думаю, що краще мати ім'я файлу з довгим рядком та UUID, ().
MysticCodes

6
Я думаю, uuid.uuid4().hexбуло б кращим вибором, див. Деталі тут .
Gray Li

4
@ToloPalmer: Швидше за все, що центральний процесор вашого комп’ютера має помилку обробки, яка змушує його завантажувати неправильний файл, ніж створюваний UUID стикається з будь-яким існуючим значенням. UUID створює унікальну назву в моделі обчислень, яка розуміє, що не всі обчислення є чистою математикою.
GManNickG

2
Вибачте за моє незнання старий коментар ... Дійсно, це не унікально, але дуже малоймовірно, що він зіткнеться, тому хороший вибір;)
Толо Палмер

51

Якщо ви хочете створити тимчасові файли в Python, існує модуль, який називається tempfile у стандартних бібліотеках Python . Якщо ви хочете запустити інші програми для роботи з файлом, використовуйте tempfile.mkstemp () для створення файлів та os.fdopen () для доступу до дескрипторів файлів, які надає mkstemp ().

До речі, ви кажете, що запускаєте команди з програми Python? Ви майже напевно повинні використовувати модуль підпроцесу .

Тож ви можете досить весело писати код, який виглядає так:

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)

Запустивши це, ви повинні виявити, що catкоманда працювала чудово, але тимчасовий файл був видалений у finallyблоці. Майте на увазі, що у вас є видалити тимчасовий файл, який mkstemp () повертає самостійно - бібліотека не може знати, коли ви закінчили з цим!

(Редагувати: Я припускав, що NamedTemporaryFile робив саме те, що вам потрібно, але це може бути не так зручно - файл видаляється негайно, коли об’єкт тимчасового файлу закривається, а інші процеси відкривають файл до того, як ви його закрили. не працюватиме на деяких платформах, зокрема Windows. На жаль, не вдалося з мого боку.)


використання NamedTemporaryFile - це, мабуть, те, що вони хочуть (якщо вони не хочуть, щоб він залишався на сервері, і тоді вони можуть використовувати "tempfile.NamedTemporaryFile (delete = False)")
Теренс Хонлес,

Чи можу я також зробити це ім'я тимчасового файлу унікальним? так що я можу зберегти його пізніше, коли підпроцес завершиться з унікальною назвою
MysticCodes 02

@Terence Honles: Я спочатку запропонував tempfile.NamedTemporaryFile (), але ви насправді не можете використовувати це для створення тимчасових файлів, до яких інші процеси можуть отримати доступ у Windows. Однак NamedTemporaryFile (delete = False), безумовно, чистіший . @ user343934: tempfile.mkstemp () гарантовано дасть вам унікальне ім'я при кожному його виклику - він генерує імена випадковим чином і використовує засоби ОС (O_EXCL, якщо вам цікаво), щоб уникнути зіткнень.
Річард Баррелл,

вау, я не знав, що це не працює на вікнах ... невдача :( ... мабуть, це добре знати
Terence Honles

@Terence Honles: NamedTemporaryFile () насправді не справляється з Windows (наскільки мені відомо), але ви не можете закрити файл, не видаливши його теж, і (наскільки я розумію семантику файлів у Windows) жодна інша програма не може відкрити файл, поки його відкрито. Я можу помилятися; семантика використання кількох процесів, що мають спільний файл під Windows, могла змінитися з моєї останньої перевірки.
Річард Баррелл,

32

uuidМодуль буде хорошим вибір, я вважаю за краще використовувати в uuid.uuid4().hexякості випадкового імені , тому що він буде повертати шестнадцатеричную рядок без дефісів .

import uuid
filename = uuid.uuid4().hex

Результати повинні сподобатися:

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

1
Яка проблема з тире?
Девід Лопес,

15

Можливо, вам потрібен унікальний тимчасовий файл?

import tempfile

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

print f.name
f.close()

f відкривається файл. delete=Falseозначає не видаляти файл після закриття.

Якщо вам потрібен контроль над іменем файлу, є необов’язкові prefix=...та suffix=...аргументи, які приймають рядки. Див. Https://docs.python.org/3/library/tempfile.html .


Це чудово, якщо вам не потрібно контролювати ім’я файлу.
hiwaylon

1
Це має бути tmpfile.NamedTemporaryFile, а не просто NamedTemporaryFile.
user1993015

w+bє типовим mode. Використання будь-яких tempfileфункціональних можливостей має недолік неправильних дозволів доступу до файлів: tempfileдокументи, що використовуються os.O_TMPFILEяк маска, але нормальне створення файлів поважає os.umask().
m8mble

8

Ви можете використовувати DATETIME модуль

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

Зверніть увагу: я використовую, replaceоскільки двокрапки не дозволяються в іменах файлів у багатьох операційних системах.

Ось і все, це дасть вам унікальне ім’я файлу кожного разу.


2
Якщо імена файлів не створюються одразу одне за одним (наприклад, у циклі). Тоді вони однакові.
skjerns

1

Я зіткнувся з цим запитанням і додам своє рішення для тих, хто може шукати щось подібне. Мій підхід полягав у тому, щоб просто створити випадкову назву файлу із asciiсимволів. Це буде унікально з великою ймовірністю.

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
Очевидна відповідь на питання стосувалася пакету uuid. Однак мій цільовий сервер має python 2.4, жоден пакет uuid та оновлення не дозволено власником сервера через несумісність застарілого програмного забезпечення, тому ця відповідь працює для мене.
Альберто Гаона

1
Мені особливо подобається така відповідь: можна легко налаштувати специфікації проекту.
swdev

1
1) Тут немає жодної причини використовувати рекурсію, особливо необмежену. 2) Існує умова перегонів між часом, який path.exists()повертається, Falseі часом, коли споживач фактично відкриває файл.
Джонатан Рейнхарт,

1

Це можна зробити за допомогою унікальної функції в модулі ufp.path .

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

якщо поточний шлях існує файл 'test.ext'. ufp.path.unique повернення функції './test (d1) .ext'.


6
ufp є частиною drupal? не стандартний модуль
ендоліт

1

Щоб створити унікальний шлях до файлу, якщо він існує, використовуйте випадковий пакет, щоб створити нове ім'я рядка для файлу. Ви можете вказати код нижче для того ж.

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

Тепер ви можете використовувати цей шлях для створення файлу відповідно.


1

Якщо вам потрібні короткі унікальні ідентифікатори як імені вашого файлу, спробуйте shortuuid, shorttuuid використовує малі та великі літери та цифри, а також видаляє подібні на вигляд символи, такі як l, 1, I, O та 0.

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

у порівнянні з

>>> import uuid
>>> unique_filename = str(uuid.uuid4())
>>> len(unique_filename)
36
>>> unique_filename
'2d303ad1-79a1-4c1a-81f3-beea761b5fdf'
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.