Python: как создать уникальное имя файла?


95

У меня есть веб-форма на Python с двумя вариантами: загрузка файла и текстовое поле . Мне нужно взять значения из каждого и передать их другой программе командной строки. Я могу легко передать имя файла с параметрами загрузки файла, но я не уверен, как передать значение текстового поля.

Я думаю, что мне нужно сделать следующее:

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

Я не уверен, как создать уникальное имя файла. Может ли кто-нибудь дать мне несколько советов о том, как создать уникальное имя файла? Приветствуются любые алгоритмы, предложения и строки кода.

Спасибо за вашу заботу


1
Я отредактировал ваш вопрос, чтобы сделать его более понятным. Сообщите мне, если я что-то неправильно истолковал!
Culix 01

Ответы:


147

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

import uuid

unique_filename = str(uuid.uuid4())

Извините, я работаю над платформой Windows, поэтому не знаю, как обрабатывать подпроцесс
MysticCodes

uuid, кажется, создает длинную уникальную строку. Я не думаю, что лучше иметь имя файла с длинной строкой и UUID, () в нем.
MysticCodes 03

6
Думаю, uuid.uuid4().hexбыло бы лучше, подробности смотрите здесь .
Грей Ли

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

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

51

Если вы хотите создавать временные файлы в Python, в стандартных библиотеках Python есть модуль под названием tempfile . Если вы хотите запустить другие программы для работы с файлом, используйте 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

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

вау, я не знал, что это не работает с Windows ... Ошибка :( ... Я думаю, это полезно знать
Теренс Хонлес

@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 является частью друпала? нестандартный модуль
endolith

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, shortuuid использует строчные и прописные буквы и цифры и удаляет похожие символы, такие как 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.